Page MenuHome GnuPG

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
This document is not UTF8. It was detected as ISO-8859-1 (Latin 1) and converted to UTF8 for display.
diff --git a/AUTHORS b/AUTHORS
index 062af1029..ca125fdd1 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,72 +1,78 @@
Authors of GNU Privacy Guard (GnuPG).
Werner Koch. Designed and implemented GnuPG.
GNUPG Matthew Skala 1998-08-10
Disclaims changes.
mskala@ansuz.sooke.bc.ca
Wrote cipher/twofish.c.
GNUPG Natural Resources Canada 1998-08-11
Disclaims changes by Matthew Skala.
GNUPG Michael Roth Germany 1998-09-17
Assigns changes.
mroth@nessie.de
Wrote cipher/des.c.
GNUPG Niklas Hernaeus 1998-09-18
Disclaims changes.
nh@df.lth.se
Weak key patches.
TRANSLATIONS Marco d'Itri 1997-02-22
Disclaimer. [it]
md@linux.it
TRANSLATIONS Gael Queri 1998-09-08
Disclaimer. [fr]
gqueri@mail.dotcom.fr
TRANSLATIONS Walter Koch 1998-09-08
Disclaimer. [de]
walterk@dip.de
TRANSLATIONS Gregory Steuck 1998-10-20
Disclaimer. [ru?]
steuck@iname.com
TRANSLATIONS Urko Lusa ??????????
es_ES.po
TRANSLATIONS Thiago Jung Bauermann ????????????????
pt_BR.po
Other notes:
============
This program uses the zlib compression library written by
Jean-loup Gailly and Mark Adler.
Most of the stuff in mpi has been taken from the GMP library.
+[Who is the author??]
-The file cipher/rndunix.c is heavily based on Peter Gutmann's
-rndunix.c from cryptlib. - He promised to add the GPL as an alternative
-license to this and some other files. We don't have a disclaimer for
-this file, but due to the fact that this is only needed for non-free
-system we can easily remove this from the distribution and put it as
-a module on some FTP server.
+The keybox implementation is based on GDBM 1.7.3 by Philip A. Nelson.
-The RPM specs file scripts/gnupg.specs has been contributed by
-Caskey L. Dickson and Reuben Sumner.
+The file cipher/rndunix.c is based on Peter Gutmann's rndunix.c from
+cryptlib. - He promised to add the GPL as an alternative license to
+this and some other files. We don't have a disclaimer yet, but due
+to the fact that this is only needed for non-free systems we can
+easily remove this from the distribution and put it as an extra module
+on the FTP server.
+
+The files in debian/ are by James Troup who is the Debian maintainer
+for GnuPG.
+
+The RPM specs file scripts/gnupg.spec has been contributed by
+several people.
diff --git a/ChangeLog b/ChangeLog
index f1ab556db..839ad6994 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,143 +1,147 @@
+Wed Dec 23 13:18:14 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
+
+ * README: Replaced the command overview with a short intro.
+
Sat Dec 12 18:40:32 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* configure.in: Add check for dlopen in libc (Greg Troxel)
and a new define
* acconfig.h (DLSYM_NEEDS_UNDERSCORE): New.
Thu Dec 10 20:15:36 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* acinclude.m (GNUPG_CHECK_PIC): New
* configure.in, acinclude.m4: Renamed all WK_ to GNUPG_
Tue Dec 8 15:09:29 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* VERSION: Set to 0.4.5
Wed Nov 25 12:38:29 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in (USE_RNDLINUX): New.
Fri Nov 20 19:34:57 1998 Werner Koch (wk@isil.d.shuttle.de)
* VERSION: Released 0.4.4
* configure.in (try_asm_modules): For option --disable-asm
Tue Nov 10 19:32:40 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in (MPI_SFLAGS): New.
Tue Nov 10 13:44:53 1998 Werner Koch (wk@isil.d.shuttle.de)
* ABOUT-NLS: New
* configure.in (AC_REVISION): New.
Sun Nov 8 18:20:35 1998 Werner Koch (wk@isil.d.shuttle.de)
* VERSION: Set to 0.4.3
Sun Oct 25 19:49:37 1998 Werner Koch (wk@isil.d.shuttle.de)
* Makefile.am (g10defs.h): New macro GNUPG_DATADIR.
Wed Oct 21 17:24:24 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in: Removed gettext kludge
* acinclude.m4: Add patched AM_WITH_NKS macro
Tue Oct 20 19:03:36 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in: Kludge to make AM_GNU_GETTEXT work,
changed some macors to more modern versions. Also
changeg the all makefiles to remove duplicate ../intl.
* acinclude.m4: Removed the gettext stuff, as this
already comes with automake now.
Wed Oct 14 12:11:34 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in (NAME_OF_DEV_RANDOM): New.
(DYNLINK_MOD_CFLAGS): New.
Thu Oct 8 10:55:15 1998 Werner Koch (wk@isil.d.shuttle.de)
* Makefile.am (g10defs.h): creates include file
* acconfig.h: now includes g10defs.h
* configure.in: Removed G10_LOCALEDIR and GNUPG_LIB
Thu Sep 17 18:49:40 1998 Werner Koch (wk@(none))
* Makefile.am (dist-hook): Now creates RPM file.
* scripts/gnupg.spec: New template file for RPMs
Thu Jul 30 19:17:07 1998 Werner Koch (wk@(none))
* acinclude.h (WK_CHECK_IPC): New
* configure.in : Add checks for SysV IPC
Thu Jun 25 11:18:49 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in (--disable-dynload): New.
Wed Jun 10 07:48:59 1998 Werner Koch,mobil,,, (wk@tobold)
* configure.in (GNUPG_LIBDIR): New.
Mon May 25 19:10:59 1998 Werner Koch (wk@isil.d.shuttle.de)
* rand-unix.c (fast_random_poll): fixed syntax bug.
Mon May 11 10:21:31 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in (PRINTABLE_OS_NAME): Linux is now GNU/Linux
Tue Apr 14 19:08:05 1998 Werner Koch (wk@isil.d.shuttle.de)
* [all files]: Applied Matthew Skala's typo and grammar fixes.
Wed Mar 4 10:32:40 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in (getrusage,gettimeofday): New tests.
Fri Feb 27 13:14:17 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in (--disable-m-guard): New.
Thu Feb 26 17:09:27 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in, acinclude.m4, intl/, po/: New macros taken
from GNOME, switched to automake 1.2f
Thu Feb 26 09:05:46 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in (doc/Makefile): New
Thu Feb 26 07:40:47 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in: Changed gettext stuff
Wed Feb 25 11:44:10 1998 Werner Koch (wk@isil.d.shuttle.de)
* checks/*test : restructured the directory.
Tue Feb 24 15:59:12 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in: Changed the name of the package to GNUPG and
chnaged several other names too.
Wed Feb 18 17:36:45 1998 Werner Koch (wk@isil.d.shuttle.de)
* Makefile.am (checks): New.
Sat Feb 14 15:37:55 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in (mpi_config_done): Removed asm links caching.
Sat Feb 14 14:02:20 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in (PRINTABLE_OS_NAME): New.
* acconfig.h: Likewise.
Fri Feb 13 19:43:41 1998 Werner Koch (wk@isil.d.shuttle.de)
* configure.in : Fixed zlib stuff
* Makefile.am: Likewise
diff --git a/INSTALL b/INSTALL
index d5bf12e6b..ac59f6115 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,281 +1,290 @@
Please read the Basic Installation section somewhere below.
Configure options for GNUPG
===========================
--with-included-zlib Forces usage of the local zlib sources. Default is
to use the (shared) library of the system.
--with-included-gettext Forces usage of the local gettext sources instead of
the one provided by your system.
--disable-nls Disable NLS support (See ABOUT-NLS)
--enable-m-debug Compile with the integrated malloc debugging stuff.
This makes the program slower but is checks every
free operation and can be used to create statistics
of memory usage. If this option is used the program
option "--debug 32" displays every call to a a malloc
function (this makes the program *really* slow), the
option "--debug 128" displays a memory statistic after
the program run.
--disable-m-guard Disable the integrated malloc checking code. As a
side-effect, this removes all debugging code and uses
the -O2 flag for all C files.
--disable-dynload If you have problems with dynamic loading, this option
disables all dynamic loading stuff.
--disable-asm Do not use assembler modules.
Problems
========
If you get unresolved externals "gettext" you should run configure again
with the option "--with-included-gettext"; this is version 0.10.35 which
is available at alpha.gnu.org.
If you have other compile problems, try the configure options
"--with-included-zlib" or "--disable-nls" (See ABOUT-NLS)
or --disable-dynload.
I can't check all assembler files, so if you have problems assembling them
(or the program crashes) use --disable-asm with ./configure.
The configure scripts may consider several subdirectories to get all
available assembler files; be sure to delete the correct ones. The
assembler replacements are in C and in mpi/generic; never delete udiv-qrnnd.S
in any CPU directory, because there may be no C substitute.
Don't forget to delete "config.cache" and run "./config.status --recheck".
The Random Device
=================
-The current version of GNUPG needs the support of a random device.
-If there is no such device, it uses a very simple RNG, which does
-not generate strong random numbers.
Random devices are available in Linux, FreeBSD and OpenBSD.
The device files may not exist on your system, please check this
and create them if needed.
The Linux files should look like this:
cr--r--r-- 1 root sys 1, 8 May 28 1997 /dev/random
cr--r--r-- 1 root sys 1, 9 Feb 16 08:23 /dev/urandom
You can create them with:
mknod /dev/random c 1 8
mknod /dev/urandom c 1 9
The FreeBSD files [from the 970202 snapshot]:
crw-r--r-- 1 root wheel 2, 3 Feb 25 16:54 /dev/random
crw-r--r-- 1 root wheel 2, 4 Feb 25 16:54 /dev/urandom
You can create them with:
mknod /dev/random c 2 3
mknod /dev/urandom c 2 4
+Unices without a random devices must use another entropy collector
+which is called rndunix and available as an extension module. You
+should put this in your ~/.gnupg/options file:
+===8<====================
+load-extension rndunix
+===>8====================
+This collector works by running a lot of tools which yields more or
+less unpredictable output and fedds this as entropy into the random
+generator - It should work reliable but you should check whether
+it produces good output for your kinf of Unix. There are some debug
+options to help you (see cipher/rndunix.c).
+
Installation
============
gpg is not installed as suid:root; if you want to do it, do it manually.
We will use capabilities in the future.
The ~/.gnupg directory will be created if it does not exist. Your first
action should be to create a key pair: "gpg --gen-key".
Creating a RPM package
======================
The file scripts/gnupg-x.x.x.spec is used to build a RPM package:
1. As root, copy the spec file into /usr/src/redhat/SPECS
2. copy the tar file into /usr/src/redhat/SOURCES
3. type: rpm -ba SPECS/gnupg-x.x.x.spec
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`configure' also accepts some other, not widely useful, options.
diff --git a/NEWS b/NEWS
index 5683b98bf..44827ee08 100644
--- a/NEWS
+++ b/NEWS
@@ -1,617 +1,619 @@
+Noteworthy changes in version 0.x.x
+-----------------------------------
* --export does now only exports rfc2440 compatible keys; the
old behavious is available with --export-all.
Generation of v3 ElGamal (sign and encrypt) keys is not longer
supported.
* Fixed the uncompress bug.
* Rewrote the rndunix module. There are two environment variables
used for debugging now: GNUPG_RNDUNIX_DBG give the file to write
debugging information (use "-" for stdout) and if GNUPG_RNDUNIX_DBGALL
is set, all programs which are only tried are also printed.
* New option --escape-from-lines to "dash-escape" "From " lines to
prevent mailers to change them to ">From ". This is not enabled by
- default because it is not in compliace with rfc2440. but you should
- turn it on.
+ default because it is not in compliance with rfc2440 - however, you
+ should turn it on.
Noteworthy changes in version 0.4.5
-----------------------------------
* The keyrings and the trustdb is now locked, so that
other GnuPG processes won't damage these files. You
may want to put the option --lock-once into your options file.
* The latest self-signatures are now used; this enables --import
to see updated preferences etc.
* Import of subkeys should now work.
* Random gathering modules may now be loaded as extensions. Add
such a module for most Unices but it is very experimental!
* Brazilian language support.
Noteworthy changes in version 0.4.4
-----------------------------------
* Fixed the way the key expiration time is stored. If you have
an expiration time on your key you should fix it with --edit-key
and the command "expire". I apologize for this inconvenience.
* Add option --charset to support "koi8-r" encoding of user ids.
(Not yet tested).
* Preferences should now work again. You should run
"gpgm --check-trustdb \*" to rebuild all preferences.
* Checking of certificates should now work but this needs a lot
of testing. Key validation values are now cached in the
trustdb; they should be recalculated as needed, but you may
use --check-trustdb or --update-trustdb to do this.
* Spanish translation by Urko Lusa.
* Patch files are from now on signed. See the man page
for the new option --not-dash-escaped.
* New syntax: --edit-key <userID> [<commands>]
If you run it without --batch the commands are executed and then
you are put into normal mode unless you use "quit" or "save" as
one of the commands. When in batch mode, the program quits after
the last command, so you have to use "save" if you did some changes.
It does not yet work completey, but may be used to list so the
keys etc.
Noteworthy changes in version 0.4.3
-----------------------------------
* Fixed the gettext configure bug.
* Kludge for RSA keys: keyid and length of a RSA key are
correctly reported, but you get an error if you try to use
this key (If you do not have the non-US version).
* Experimental support for keyrings stored in a GDBM database.
This is *much* faster than a standard keyring. You will notice
that the import gets slower with time; the reason is that all
new keys are used to verify signatures of previous inserted
keys. Use "--keyring gnupg-gdbm:<name-of-gdbm-file>". This is
not (yet) supported for secret keys.
* A Russian language file in the distribution (alternatives are in
the contrib directory of the FTP servers)
* commandline option processing now works as expected for GNU programs
with the execption that you can't mix options and normal arguments.
* Now --list-key lists all matching keys. This is needed in some
other places too.
Noteworthy changes in version 0.4.2
-----------------------------------
* This is only a snapshot: There are still a few bugs.
* Fixed this huge memory leak.
* Redesigned the trust database: You should run "gpgm --check-trustdb".
New command --update-trustdb, which adds new key from the public
keyring into your trustdb
* Fixed a bug in the armor code, leading to invalid packet errors.
(a workaround for this was to use --no-armor). The shorten line
length (64 instead of 72) fixes a problem with pgp5 and keyservers.
* comment packets are not anymore generated. "--export" filters
them out. One Exception: The comment packets in a secret keyring
are still used because they carry the factorization of the public
prime product.
* --import now only looks for KEYBLOCK headers, so you can now simply
remove the "- " in front of such a header if someone accdently signed
such a message or the keyblock is part of a cleartext signed message.
* --with-colons now lists the key expiration time and not anymore
the valid period.
* Some keyblocks created with old releases have a wrong sequence
of packets, so that the keyservers don't accept these keys.
Simply using "--edit-key" fixes the problem.
* New option --force-v3-sigs to generate signed messages which are
compatible to PGP 5.
* Add some code to support DLD (for non ELF systems) - but this is
not tested because my BSD box is currently broken.
* New command "expire" in the edit-key menu.
Noteworthy changes in version 0.4.1
-----------------------------------
* A secondary key is used when the primary key is specified but cannot
be used for the operation (if it is a sign-only key).
* GNUPG can now handle concatenated armored messages: There is still a
bug if different kinds of messages are mixed.
* Iterated+Salted passphrases now work. If want to be sure that PGP5
is able to handle them you may want to use the options
"--s2k-mode 3 --s2k-cipher-algo cast5 --s2k-digest-algo sha1"
when changing a passphrase.
* doc/OpenPGP talks about OpenPGP compliance, doc/HACKING gives
a few hints about the internal structure.
* Checked gnupg against the August 1998 draft (07) and I believe
it is in compliance with this document (except for one point).
* Fixed some bugs in the import merging code and rewrote some
code for the trustdb.
Noteworthy changes in version 0.4.0
-----------------------------------
* Triple DES is now supported. Michael Roth did this piece of
needed work. We have now all the coded needed to be OpenPGP
compliant.
* Added a simple rpm spec file (see INSTALL).
* detached and armored signatures are now using "PGP SIGNATURE",
except when --rfc1991 is used.
* All times which are not in the yyy-mm-dd format are now printed
in local time.
Noteworthy changes in version 0.3.5
-----------------------------------
* New option --throw-keyid to create anonymous enciphered messages.
If gpg detects such a message it tires all available secret keys
in turn so decode it. This is a gnupg extension and not in OpenPGP
but it has been discussed there and afaik some products use this
scheme too (Suggested by Nimrod Zimmerman).
* Fixed a bug with 5 byte length headers.
* --delete-[secret-]key is now also availabe in gpgm.
* cleartext signatures are not anymore converted to LF only.
* Fixed a trustdb problem. Run "gpgm --check-trustdb" to fix old
trust dbs.
* Building in another directory should now work.
* Weak key detection mechanism (Niklas Hernaeus).
Noteworthy changes in version 0.3.4
-----------------------------------
* New options --comment and --set-filename; see g10/OPTIONS
* yes/no, y/n localized.
* Fixed some bugs.
Noteworthy changes in version 0.3.3
-----------------------------------
* IMPORTANT: I found yet another bug in the way the secret keys
are encrypted - I did it the way pgp 2.x did it, but OpenPGP
and pgp 5.x specifiy another (in some aspects simpler) method.
To convert your secret keys you have to do this:
1. Build the new release but don't install it and keep
a copy of the old program.
2. Disable the network, make sure that you are the only
user, be sure that there are no trojan horses etc ....
3. Use your old gpg (version 0.3.[12]) and set the
passphrases of ALL your secret keys to empty!
(gpg --change-passphrase your-user-id).
4. Save your ownertrusts (see the next point)
5. rm ~/.gnupg/trustd.gpg
6. install the new version of gpg (0.3.3)
7. For every secret key call "gpg --edit-key your-user-id",
enter "passwd" at the prompt, follow the instructions and
change your passward back, enter "save" to store it.
8. Restore the ownertrust (see next point).
* The format of the trust database has changed; you must delete
the old one, so gnupg can create a new one.
IMPORTANT: Use version 0.3.[12] to save your assigned ownertrusts
("gpgm --list-ownertrust >saved-trust"); then build this new version
and restore the ownertrust with this new version
("gpgm --import-ownertrust saved-trust"). Please note that
--list-ownertrust has been renamed to --export-ownertrust in this
release and it does now only export defined ownertrusts.
* The command --edit-key now provides a commandline driven menu
which can be used vor vaious tasks. --sign-key is only an
an alias to --edit-key and maybe removed in future: use the
command "sign" of this new menu - you can select which user ids
you want to sign.
* Alternate user ids can now be created an signed.
* Owner trust values can now be changed with --edit-key (trust)
* GNUPG can now run as a coprocess; this enables sophisticated
frontends. tools/shmtest.c is a simple sample implemenation.
This needs some more work: all tty_xxx() are to be replaced
by cpr_xxx() and some changes in the display logics is needed.
* Removed options --gen-prime and --gen-random.
* Removed option --add-key; use --edit-key instead.
* Removed option --change-passphrase; use --edit-key instead.
* Signatures are now checked even if the output file could not
be created. Command "--verify" tries to find the detached data.
* gpg now disables core dumps.
* compress and symmetric cipher preferences are now used.
Because there is no 3DES yet, this is replaced by Blowfish.
* We have added the Twofish as an experimental cipher algorithm.
Many thanks to Matthew Skala for doing this work.
Twofish is the AES submission from Schneier et al.; see
"www.counterpane.com/twofish.html" for more information.
* Started with a help system: If you enter a question mark at some
prompt; you should get a specific help for this prompt.
* There is no more backup copy of the secret keyring.
* A lot of new bugs. I think this release is not as stable as
the previous one.
Noteworthy changes in version 0.3.2
-----------------------------------
* Fixed some bugs when using --textmode (-seat)
* Now displays the trust status of a positive verified message.
* Keyrings are now scanned in the sequence they are added with
--[secret-]keyring. Note that the default keyring is implictly
added as the very first one unless --no-default-keyring is used.
* Fixed setuid and dlopen bug.
Noteworthy changes in version 0.3.1
-----------------------------------
* Partial headers are now written in the OpenPGP format if
a key in a v4 packet is used.
* Removed some unused options, removed the gnupg.sig stuff.
* Key lookup by name now returns a key which can be used for
the desired action.
* New options --list-ownertrust (gpgm) to make a backup copy
of the ownertrust values you assigned.
* clear signature headers are now in compliance with OpenPGP.
Noteworthy changes in version 0.3.0
-----------------------------------
* New option --emulate-checksum-bug. If your passphrase does not
work anymore, use this option and --change-passphrase to rewrite
your passphrase.
* More complete v4 key support: Preferences and expiration time
is set into the self signature.
* Key generation defaults to DSA/ElGamal keys, so that new keys are
interoperable with pgp5
* DSA key generation is faster and key generation does not anymore
remove entropy from the random generator (the primes are public
parameters, so there is really no need for a cryptographic secure
prime number generator which we had used).
* A complete new structure for representing the key parameters.
* Removed most public key knowledge into the cipher libray.
* Support for dynamic loading of new algorithms.
* Moved tiger to an extension module.
Noteworthy changes in version 0.2.19
------------------------------------
* Replaced /dev/urandom in checks with new tool mk-tdata.
* Some assembler file cleanups; some more functions for the Alpha.
* Tiger has now the OpenPGP assigned number 6. Because the OID has
changed, old signatures using this algorithm can't be verified.
* gnupg now encrypts the compressed packed and not any longer in the
reverse order; anyway it can decrypt both versions. Thanks to Tom
for telling me this (not security related) bug.
* --add-key works and you are now able to generate subkeys.
* It is now possible to generate ElGamal keys in v4 packets to create
valid OpenPGP keys.
* Some new features for better integration into MUAs.
Noteworthy changes in version 0.2.18
------------------------------------
* Splitted cipher/random.c, add new option "--disable-dev-random"
to configure to support the development of a random source for
other systems. Prepared sourcefiles rand-unix.c, rand-w32.c
and rand-dummy.c (which is used to allow compilation on systems
without a random source).
* Fixed a small bug in the key generation (it was possible that 48 bits
of a key were not taken from the random pool)
* Add key generation for DSA and v4 signatures.
* Add a function trap_unaligned(), so that a SIGBUS is issued on
Alphas and not the slow emulation code is used. And success: rmd160
raised a SIGBUS.
* Enhanced the formatting facility of argparse and changed the use of
\r,\v to @ because gettext does not like it.
* New option "--compress-algo 1" to allow the creation of compressed
messages which are readable by PGP and "--print-md" (gpgm) to make
speed measurement easier.
Noteworthy changes in version 0.2.17
------------------------------------
* Comment packets are now of private type 61.
* Passphrase code still used a 160 bit blowfish key, added a
silly workaround. Please change your passphrase again - sorry.
* Conventional encryption now uses a type 3 packet to describe the
used algorithms.
* The new algorithm number for Blowfish is 20, 16 is still used for
encryption only; for signing it is only used when it is in a v3 packet,
so that GNUPG keys are still valid.
Noteworthy changes in version 0.2.16
------------------------------------
* Add experimental support for the TIGER/192 message diigest algorithm.
(But there is only a dummy ASN OID).
* Standard cipher is now Blowfish with 128 bit key in OpenPGP's CFB
mode. I renamed the old cipher to Blowfish160. Because the OpenPGP
group refused to assign me a number for Blowfish160, I have to
drop support for this in the future. You should use
"--change-passphrase" to recode your current passphrase with 128
bit Blowfish.
Noteworthy changes in version 0.2.15
------------------------------------
* Fixed a bug with the old checksum calculation for secret keys.
If you run the program without --batch, a warning does inform
you if your secret key needs to be converted; simply use
--change-passphrase to recalculate the checksum. Please do this
soon, as the compatible mode will be removed sometime in the future.
* CAST5 works (using the PGP's special CFB mode).
* Again somewhat more PGP 5 compatible.
* Some new test cases
Noteworthy changes in version 0.2.14
------------------------------------
* Changed the internal handling of keyrings.
* Add support to list PGP 5 keyrings with supkeys
* Timestamps of signatures are now verified.
* A expiration time can now be specified during key generation.
* Some speedups for Blowfish and SHA-1, rewrote SHA-1 transform.
Reduced the amount of random bytes needed for key generation in
some cases.
Noteworthy changes in version 0.2.13
------------------------------------
* Verify of DSA signatures works.
* Re-implemented the slower random number generator.
Noteworthy changes in version 0.2.12
------------------------------------
* --delete-key checks that there is no secret key. The new
option --delete-secret-key maybe used to delete a secret key.
* "-kv" now works as expected. Options "--list-{keys,sigs]"
and "--check-sigs" are now working.
* New options "--verify" and "--decrypt" to better support integration
into MUAs (partly done for Mutt).
* New option "--with-colons" to make parsing of key lists easier.
Noteworthy changes in version 0.2.11
------------------------------------
* GPG now asks for a recipient's name if option "-r" is not used.
* If there is no good trust path, the program asks whether to use
the public keys anyway.
* "--delete-key" works for public keys. What semantics shall I use
when there is a secret key too? Delete the secret key or leave him
and auto-regenerate the public key, netxt time the secret key is used?
Noteworthy changes in version 0.2.10
------------------------------------
* Code for the alpha is much faster (about 20 times); the data
was misaligned and the kernel traps this, so nearly all time
was used by system to trap the misalignments and to write
syslog messages. Shame on me and thanks to Ralph for
pointing me at this while drinking some beer yesterday.
* Changed some configure options and add an option
--disable-m-guard to remove the memory checking code
and to compile everthing with optimization on.
* New environment variable GNUPGHOME, which can be used to set
another homedir than ~/.gnupg. Changed default homedir for
Windoze version to c:/gnupg.
* Fixed detached signatures; detached PGP signatures caused a SEGV.
* The Windoze version works (as usual w/o a strong RNG).
Noteworthy changes in version 0.2.9
-----------------------------------
* Fixed FreeBSD bug.
* Added a simple man page.
* Switched to automake1.2f and a newer gettext.
Noteworthy changes in version 0.2.8
-----------------------------------
* Changed the name to GNUPG, the binaries are called gpg and gpgm.
You must rename rename the directory "~/.g10" to ~/.gnupg/, rename
{pub,sec}ring.g10 to {pub,sec}ring.gpg, trustdb.g10 to trustdb.gpg
and g10.sig to gnupg.sig.
* New or changed passphrases are now salted.
Noteworthy changes in version 0.2.7
-----------------------------------
* New command "gen-revoke" to create a key revocation certificate.
* New option "homedir" to set the homedir (which defaults to "~/.g10").
This directory is created if it does not exists (only the last
part of the name and not the complete hierarchy)
* Command "import" works. (Try: "finger gcrypt@ftp.guug.de|g10 --import")
* New commands "dearmor/enarmor" for g10maint. These are mainly
used for internal test purposes.
* Option --version now conforming to the GNU standards and lists
the available ciphers, message digests and public key algorithms.
* Assembler code for m68k (not tested).
* "make check" works.
Noteworthy changes in version 0.2.6
-----------------------------------
* Option "--export" works.
Noteworthy changes in version 0.2.5
-----------------------------------
* Added zlib for systems which don't have it.
Use "./configure --with-zlib" to link with the static version.
* Generalized some more functions and rewrote the encoding of
message digests into MPIs.
* Enhanced the checkit script
Noteworthy changes in version 0.2.4
-----------------------------------
* nearly doubled the speed of the ElGamal signature verification.
* backup copies of keyrings are created.
* assembler stuff for Pentium; gives about 15% better perfomance.
* fixed a lot of bugs.
Noteworthy changes in version 0.2.3
-----------------------------------
* Found a bug in the calculation of ELG fingerprints. This is now
fixed, but all existing fingerprints and keyids for ELG keys
are not any more valid.
* armor should now work; including clear signed text.
* moved some options to the new program g10maint
* It's now 64 bit clean and runs fine on an alpha--linux.
* Key generation is much faster now. I fixed this by using not
so strong random number for the primes (this was a bug because the
ElGamal primes are public parameters and it does not make sense
to generate them from strong random). The real secret is the x value
which is still generated from strong (okay: /dev/random) random bits.
* added option "--status-fd": see g10/OPTIONS
* We have secure memeory on systems which support mlock().
It is not complete yet, because we do not have signal handler
which does a cleanup in very case.
We should also check the ulimit for the user in the case
that the admin does not have set a limit on locked pages.
* started with internationalization support.
* The logic to handle the web of trust is now implemented. It is
has some bugs; but I'm going to change the algorithm anyway.
It works by calculating the trustlevel on the fly. It may ask
you to provide trust parameters if the calculated trust probability
is too low. I will write a paper which discusses this new approach.
* a couple of changes to the configure script.
* New option "--quick-random" which uses a much quicker random
number generator. Keys generated while this option is in effect
are flags with "INSECURE!" in the user-id. This is a development
only option.
* Read support for new version packets (OpenPGP).
* Comment packets are now of correct OpenPGP type 16. Old comment
packets written by G10 are detected because they always start with
a hash which is an invalid version byte.
* The string "(INSECURE!)" is appended to a new user-id if this
is generated on a system without a good random number generator.
diff --git a/PROJECTS b/PROJECTS
index 0ffd0fce1..deaf4e56b 100644
--- a/PROJECTS
+++ b/PROJECTS
@@ -1,36 +1,47 @@
- * Check if an object (a message, detached sign, public key, or whatever)
- is signed by definite user, i.e. define user
- (userid, or any other unique identification) on command line.
- --> NO: Use a script and --status-fd
+ * Check if an object (a message, detached sign, public key, or whatever)
+ is signed by definite user, i.e. define user
+ (userid, or any other unique identification) on command line.
+ --> NO: Use a script and --status-fd
* Change the internal represention of keyid into a struct which
can also hold the localid and extend the localid to hold information
of the subkey number because two subkeys may have the same keyid.
* signature verification is done duplicated on import: in import.c and
- tehn in trustdb.c too. Maybe we can use a flag to skip the actual
+ then in trustdb.c too. Maybe we can use a flag to skip the actual
verification process (this should work if we use the same keyblock,
but I'm not sure how to accomplish that). Another way is to allow
the import of bogus data and let trustdb mark these keys as invalid;
I see an advantage in this that it may help to prevent a DoS on a
keyserver by sending him a lot of bogus signatures which he has
to check - Needs further investigation.
- * abstraction of the MPI
+ * Add a way to override the current cipher/md implementations
+ by others (using extensions)
- * Add a way to override the current cipher/md implementations
- by others (using extensions)
+ * Not GnuPG replated: What about option completion in bash?
+ Can "--dump-options" be used for this or should we place the
+ options in a special ELF segment?
- * Not GnuPG replated: What about option completion in bash?
- Can "--dump-options" be used for this or should we place the
- options in a special ELF segment?
-
- * Split key support (n-out-of-m)
+ * Split key support (n-out-of-m)
* Check Berkeley DB - it is in glibc - any licensing problems?
* add an option to re-create a public key from a secret key; we
can do this in trustdb.c:verify_own_keys.
(special tool?)
+ * rewrite --list-packets or put it into another tool.
+
+ * We need a maintainence pass over the trustdb which flags
+ signatures as expired if the key used to make the signature has
+ expired. Maybe it is a good idea to store the exiration time
+ in the key record of the trustdb.
+ * write a tool to extract selected keys from a file.
+
+ * Change the buffering to a mbuf like scheme? Need it for PSST anyway;
+ see Michael's proposal.
+
+ * Work on the library
+
diff --git a/README b/README
index 8e78f46a7..73a83df43 100644
--- a/README
+++ b/README
@@ -1,344 +1,424 @@
------BEGIN PGP SIGNED MESSAGE-----
-
- GnuPG - The GNU Privacy Guard
- -------------------------------
- Version 0.4
-
- As you can see from the version number, the program may have some
- bugs and some features may not work at all - please report this to
- the mailing list.
-
- On a Linux box (version 2.x.x, alpha or x86 CPU) it should
- work reliably. You may create your key on such a machine and
- use it. Please verify the tar file; there is a PGP and a GnuPG
- signature available. My PGP 2 key is well known and published in
+ GnuPG - The GNU Privacy Guard
+ -------------------------------
+ Version 0.9
+
+ GnuPG is now in Beta test and you should report all bugs to the
+ mailing list (see below). The 0.9.x versions are mainly released
+ to fix all remaining serious bugs. As soon as version 1.0 is out,
+ development will continue with a 1.1 series and bug fixes for the
+ 1.0 version are released as needed.
+
+ GnuPG works best on GNU/Linux or *BSD. Other Unices are
+ also supported but not as good tested as those Freenix ones.
+ Please verify the tar file; there is a PGP2 and a GnuPG/PGP5
+ signature available. My PGP2 key is well known and published in
the "Global Trust Register for 1998", ISBN 0-9532397-0-5.
I have included my pubring as "g10/pubring.asc", which contains
the key used to make GnuPG signatures:
"pub 1024D/57548DCD 1998-07-07 Werner Koch (gnupg sig) <dd9jn@gnu.org>"
"Key fingerprint = 6BD9 050F D8FC 941B 4341 2DCC 68B7 AB89 5754 8DCD"
- Old version of gnupg are signed with this key:
- "pub 1312G/FF3EAA0B 1998-02-09 Werner Koch <wk@isil.d.shuttle.de>"
- "Key fingerprint = 8489 6CD0 1851 0E33 45DA CD67 036F 11B8 FF3E AA0B"
-
- My usual key is now:
+ My new DSA key is:
"pub 1024D/621CC013 1998-07-07 Werner Koch <werner.koch@guug.de>"
"Key fingerprint = ECAF 7590 EB34 43B5 C7CF 3ACB 6C7E E1B8 621C C013"
- You may add it to your GnuPG pubring and use it in the future to
+ You may want add it to your GnuPG pubring and use it in the future to
verify new releases. Because you verified this README file and
_checked_that_it_is_really_my PGP2 key 0C9857A5, you can be sure
that the above fingerprints are correct.
Please subscribe to g10@net.lut.ac.uk by sending a mail with
the word "subscribe" in the body to "g10-request@net.lut.ac.uk".
- This mailing is closed (only subscribers can post) to avoid spam.
+ This mailing list is a closed one (only subscribers are allowed
+ to post) to avoid misuse by folks who don't know the Netiquette
+ and trash you mailspool with commercial junk.
See the file COPYING for copyright and warranty information.
+ GnuPG is in compliance with RFC2440 (OpenPGP), see doc/OpenPGP for
+ details.
+
Due to the fact that GnuPG does not use use any patented algorithm,
- it cannot be compatible with old PGP versions, because those use
+ it cannot be compatible with PGP2 versions; PGP 2.x does only use
IDEA (which is patented worldwide) and RSA (which is patented in
the United States until Sep 20, 2000).
- GnuPG is in compliance with RFC2440 (OpenPGP), see doc/OpenPGP for
- deatils.
-
- The default algorithms are now DSA and ELGamal. ELGamal for signing
+ The default algorithms are now DSA and ElGamal. ElGamal for signing
is still available, but due to the larger size of such signatures it
is depreciated (Please note that the GnuPG implementation of ElGamal
- signatures is *not* insecure). Symmetric algorithms are: 3DES, Blowfish
- and CAST5, Digest algorithms are MD5, RIPEMD160, SHA1 and TIGER/192.
-
+ signatures is *not* insecure). Symmetric algorithms are: 3DES,
+ Blowfish and CAST5 (Twofish will come soon), available digest
+ algorithms are MD5, RIPEMD160, SHA1 and TIGER/192.
Installation
------------
Please read the file INSTALL!
Here is a quick summary:
1) "./configure"
2) "make"
3) "make install"
- 4) You end up with a binary "gpg" in /usr/local/bin
+ 4) You end up with the binaries "gpg" and "gpgm" in /usr/local/bin.
+
+ 5) Optional, but suggested: install the binary "gpg" as suid root.
+
- 5) Optional, but suggested: install the program "gpg" as suid root.
+ Intro
+ -----
+ This is a brief overview how to use GnuPG - it is highly suggested
+ that you read the manual^H^H^H more information about the use
+ of cryptography. GnuPG is only the technical tool to do it and
+ the security highly depends on that YOU KNOW WHAT YOU ARE DOING.
+ If you already have a DSA key from PGP 5 (they call them DH/ElGamal)
+ you can simply copy the pgp keyrings over the GnuPG keyrings after
+ running gpg once, so that it can create the correct directory.
- Key Generation
- --------------
+ The normal way to create a key is:
gpg --gen-key
This asks some questions and then starts key generation. To create
- good random numbers for prime number generation, it uses a /dev/random
- which will only emit bytes if the kernel can gather enough entropy.
- If you see no progress, you should start some other activities such
- as mouse moves, "find /" or using the keyboard (in another window).
- Because we have no hardware device to generate randomness we have to
- use this method.
-
- You should make a revocation certificate in case someone gets
- knowledge of your secret key or you forgot your passphrase:
+ good random numbers for the key parameters, GnuPG needs to gather
+ enough noise (entropy) from your system. If you see no progress
+ during key generation you should start some other activities such
+ as mouse moves or hitting on the CTRL and SHIFT keys.
+
+ Generate a key ONLY on a machine where you have direct physical
+ access - don't do it over the network or on a machine used also
+ by others - especially if you have no access to the root account.
+
+ When you are asked for a passphrase; use a good one which you can easy
+ remember. Don't make the passphrase too long because you have to
+ type it for every decryption or signing; but - AND THIS IS VERY
+ IMPORTANT - use a good one which is not easily guessable as the
+ security of the whole system relies on your secret key and the
+ passphrase is used to protect this secret key in case someone was
+ able to get access to your secret keyring. A good way to select
+ a passphrase is to figure out a short nonsense sentence which makes
+ some sense for you and modify it by inserting extra spaces, non-letters
+ and changing the case of some characters - this is really easy to
+ remember especially if you associate some pictures with it.
+
+ Then you should create a revocation certificate in case someone
+ gets knowledge of your secret key or you forgot your passphrase:
gpg --gen-revoke your_user_id
Run this command and store it away; output is always ASCII armored,
so that you can print it and (hopefully never) re-create it if
your electronic media fails.
- If you decided to create a DSA key, you should add an ElGamal
- for encryption:
-
- gpg --add-key user_id_of_your_key
-
- and follow the displayed instructions (select "ElGamal using v4 packets").
-
-
- You can sign a key with this command:
-
- gpg --sign-key Donald
-
- This let you sign the key of "Donald" with your default userid.
-
- gpg --sign-key -u Karl -u Joe Donald
-
- This let you sign the key of of "Donald" with the userids of "Karl"
- and "Joe".
- All existing signatures are checked; if some are invalid, a menu is
- offered to delete some of them, and then you are asked for every user
- whether you want to sign this key.
-
- You may remove a signature at any time using the option "--edit-sig",
- which asks for the sigs to remove. Self-signatures are not removable.
-
-
-
-
- Sign
- ----
+ Now you can use your key to create digital signatures:
gpg -s file
This creates a file file.gpg which is compressed and has a signature
attached.
gpg -sa file
- Same as above, but file.gpg is ascii armored.
+ Same as above, but creates the file.asc which is ascii armored and
+ and ready for sending by mail. Note: It is better to use your
+ mailers features to create signatures (The mailer uses GnuPG to do
+ this) because the mailer has the ability to MIME encode such
+ signatures - but this is not a security issue.
gpg -s -o out file
Creates a signature of file, but writes the output to the file "out".
- If you use the option "--rfc1991", gnupg tries to me more compatible
- to RFC1991 (pgp 2.x).
+ Everyone who knows your public key (you can and should publish
+ your key by putting it on a key server, a web page or in your .plan
+ file) is now able to check whether you really signed this text;
+ gpg --verify file
- Encrypt
- -------
+ GnuPG now checks whether the signature is valid and prints an
+ appropriate message. If the signature is good, you know at least
+ that the person (or machine) has access to the secret key which
+ corresponds to the published public key.
+ If you run gpg without an option it will verify the signature and
+ create a new file which is identical to the original file. gpg
+ can also run as a filter, so that you can pipe data to verify
+ trough it:
- gpg -e -r heine file
+ cat signed-file | gpg | wc -l
- This encrypts files with the public key of "heine" and writes it
- to "file.gpg"
+ will check the signature of signed-file and then display the
+ number of lines in the original file.
- echo "hallo" | gpg -ea -r heine | mail heine
+ To send a message encrypted to someone you can use this:
- Ditto, but encrypts "hallo\n" and mails it as ascii armored message.
+ gpg -e -r heine file
+ This encrypts file with the public key of the user "heine" and
+ writes it to "file.gpg"
- Sign and Encrypt
- ----------------
+ echo "hallo" | gpg -ea -r heine | mail heine
- gpg -se -r heine file
+ Ditto, but encrypts "hallo\n" and mails it as ascii armored message
+ to the user with the mail address heine.
- This encrypts files with the public key of "heine" and writes it
- to "file.gpg" after signing it with the default user id.
+ gpg -se -r heine file
+ This encrypts file with the public key of "heine" and writes it
+ to "file.gpg" after signing it with your user id.
gpg -se -r heine -u Suttner file
- Ditto, but sign the file with the user id "Suttner"
+ Ditto, but sign the file with your alternative user id "Suttner"
- Keyring Management
- ------------------
- To export your complete keyring(s) do this:
+ GnuPG has some options to help you publish public keys; this is
+ called "exporting" a key:
- gpg --export
+ gpg --export >all-my-keys
- To export only some user ids do this:
+ exports all the keys in the keyring and writes them (in a binary format)
+ to all-my-keys. You may then mail "all-my-keys" as an MIME attachment
+ to someone else or put it on an FTP server. To export only some
+ user IDs, you give them as arguments on the command line.
- gpg --export userids
+ To mail a public key or put it on a web page you have to create
+ the key in ASCII armored format:
- Use "-a" or "--armor" to create ASCII armored output.
+ gpg --export --armor | mail panther@tiger.int
- Importing keys is done with the option, you guessed it, "--import":
-
- gpg --import [filenames]
+ This will send all your public keys to your friend panther.
- New keys are appended to the default keyring and already existing
- keys are merged. Keys without a self-signature are ignored.
+ If you have received a key from someone else you can put it
+ into your public keyring; is called "importing":
+ gpg --import [filenames]
- How to Specify a UserID
- -----------------------
- There are several ways to specify a userID, here are some examples:
+ New keys are appended to your keyring and already existing
+ keys are updated. Note that GnuPG does not allow keys which
+ are not self-signed by the user.
+
+ Because anyone can claim that the public key belongs to her
+ we must have some way to check that the public key really belongs
+ to the owner. This can be achieved by comparing the key during
+ a phone call. Sure, it is not very easy to compare a binary file
+ by reading the complete hex dump of the file - GnuPG (and nearly
+ every other program used for management of cryptographic keys)
+ provides other solutions:
+
+ gpg --fingerprint <username>
+
+ prints the so called "fingerprint" of the given username; this
+ is a sequence of hex bytes (which you may have noticed in mail
+ sigs or on business cards) which uniquely identify the public
+ key - two different keys will always have different fingerprints.
+ It is easy to compare this fingerprint by phone and I suggest
+ that you print your fingerprint on the back of your business
+ card.
+
+ If you don't know the owner of the public key you are in trouble;
+ but wait: A friend of you knows someone who knows someone who
+ has met the owner of the public key at some computer conference.
+ So all the persons between you and the public key holder may now
+ act as introducer to you; this is done by signing the keys and
+ thereby certifying the other keys. If you then trust all the
+ introducers to correctly sign other keys, you can be be sure that
+ the other key really belongs to the one who claims so.
+
+ There are 2 steps to validate a target key:
+ 1. First check that there is a complete chain
+ of signed keys from the public key you want to use
+ and your key and verify each signature.
+ 2. Make sure that you have full trust in the certificates
+ of all the introduces between the public key holder and
+ you.
+ Step 2 is the more complicated part because there is no easy way
+ for a computer to decide who is trustworthy and who is not. GnuPG
+ leaves this decision to you and will ask you for a trust value
+ (here also referenced as the owner-trust of a key) for every key
+ needed to check the chain of certificates. You may choose from:
+ a) "I don't know" - then it is not possible to use any
+ of the chains of certificates, in which this key is used
+ as an introducer, to validate the target key. Use this if
+ you don't know the introducer.
+ b) "I do not trust" - Use this if you know that the introducer
+ does not do a good job in certifying other keys. The effect
+ is the same as with a) but for a) you may later want to
+ change the value because you got new information about this
+ introducer.
+ c) "I trust marginally" - Use this if you assume that the
+ introducer knows what he is doing. Together with some
+ other marginally trusted keys, GnuPG validates the target
+ key then as good.
+ d) "I fully trust" - Use this if you really know that this
+ introducer does a good job when certifying other keys.
+ If all the introducer are of this trust value, GnuPG
+ normally needs only one chain of signatures to validate
+ a target key okay. (But this may be adjusted with the help
+ of some options).
+ These information are confidential because they give your
+ personal opinion on the trustworthy of someone else. Therefore
+ this data is not stored in the keyring but in the "trustdb"
+ (~/.gnupg/trustdb.gpg). Do not assign a high trust value just
+ because the introducer is a friend of you - decide how far she
+ understands all the implications of key signatures and you may
+ want to tell him more about public key cryptography so you
+ can later change the trust value you assigned.
+
+ Okay, here is how GnuPG helps you in key management: Most stuff is
+ done with the --edit-key command:
+
+ gpg --edit-key <keyid or username>
+
+ GnuPG displays some information about the key and then prompts
+ for a command (enter "help" to see a list of commands and see
+ the man page for a more detailed explanation). To sign a key
+ you select the user ID you want to sign by entering the number
+ which is displayed in the leftmost column (or do nothing if the
+ key has only one user ID) and then enter the command "sign" and
+ follow all the prompts. When you are ready, give the command
+ "save" (or use "quit" to cancel your actions).
+
+ If you want to sign the key with another user ID of yours, you
+ must give an "-u" option on the command line together with the
+ "--edit-key".
+
+ Normally you want to sign only one user ID because GnuPG
+ does only use one and this keeps the public key certificate
+ small. Because such key signatures are very important you
+ should make sure that the signators of your key sign a user ID
+ which is very likely to stay for a long time - choose one with an
+ email address you have full control of or do not enter an email
+ address at all. In future GnuPG will have a way to tell which
+ user ID is the one with an email address you prefer - because
+ you have no signatures on this email address it is easy to change
+ this address. Remember: Your signators sign your public key (the
+ primary one) together with one od your user IDs - so it is not possible
+ to change the user ID later without voiding all the signatures.
+
+ Tip: If you hear about a key signing party on a computer conference
+ join it because this is a very convenient way to get your key
+ certified (But remember that signatures have nothing to to with the
+ trust you assign to a key).
+
+
+ 7 Ways to Specify a User ID
+ --------------------------
+ There are several ways to specify a user ID, here are some examples:
* Only by the short keyid (prepend a zero if it begins with A..F):
"234567C4"
"0F34E556E"
"01347A56A"
"0xAB123456
* By a complete keyid:
"234AABBCC34567C4"
"0F323456784E56EAB"
"01AB3FED1347A5612"
"0x234AABBCC34567C4"
* By a fingerprint:
"1234343434343434C434343434343434"
"123434343434343C3434343434343734349A3434"
"0E12343434343434343434EAB3484343434343434"
The first one is MD5 the others are ripemd160 or sha1.
- * By an exact string (not yet implemented):
+ * By an exact string:
"=Heinrich Heine <heinrichh@uni-duesseldorf.de>"
* By an email address:
"<heinrichh@uni-duesseldorf.de>"
- This can be used by a keyserver instead of a substring to
- find this key faster.
-
- * By the Local ID (from the trustdb):
+ * By the Local ID (from the trust DB):
"#34"
- This can be used by a MUA to specify an exact key after selecting
+ This may be used by a MUA to specify an exact key after selecting
a key from GnuPG (by the use of a special option or an extra utility)
-
* Or by the usual substring:
"Heine"
"*Heine"
The '*' indicates substring search explicitly.
-
-
Batch mode
----------
If you use the option "--batch", GnuPG runs in non-interactive mode and
never prompts for input data. This does not even allow entering the
passphrase; until we have a better solution (something like ssh-agent),
- you can use the option "--passhrase-fd n", which works like PGPs
+ you can use the option "--passphrase-fd n", which works like PGPs
PGPPASSFD.
Batch mode also causes GnuPG to terminate as soon as a BAD signature is
detected.
Exit status
-----------
GnuPG returns with an exit status of 1 if in batch mode and a bad signature
has been detected or 2 or higher for all other errors. You should parse
- stderr or the output of the fd specified with --status-fd to get detailed
- information about the errors.
+ stderr or better the output of the fd specified with --status-fd to get
+ detailed information about the errors.
Esoteric commands
-----------------
gpg --list-packets datafile
Use this to list the contents of a data file. If the file is encrypted
you are asked for the passphrase, so that GnuPG is able to look at the
- inner structure of a encrypted packet.
+ inner structure of a encrypted packet. This command should be able
+ to list all kinds of rfc2440 messages.
gpgm --list-trustdb
- List the contents of the trustdb in a human readable format
+ List the contents of the trust DB in a human readable format
gpgm --list-trustdb <usernames>
List the tree of certificates for the given usernames
- gpgm --list-trust-path depth username
-
- List the possible trust paths for the given username, up to the specified
- depth. If depth is negative, duplicate introducers are not listed,
- because those would increase the trust probability only minimally.
- (you must use the special option "--" to stop option parsing when
- using a negative number). This option may create new entries in the
- trustdb.
+ gpgm --list-trust-path username
- gpgm --print-mds filenames
+ List the possible trust paths for the given username. The length
+ of such a trust path is limited by the option --max-cert-depth
+ which defaults to 5.
- List all available message digest values for the fiven filenames
-
- For more options/commands see the file g10/OPTIONS, or use "gpg --help"
-
-
- Debug Flags
- -----------
- Use the option "--debug n" to output debug information. This option
- can be used multiple times, all values are ORed; n maybe prefixed with
- 0x to use hex-values.
-
- value used for
- ----- ----------------------------------------------
- 1 packet reading/writing
- 2 MPI details
- 4 ciphers and primes (may reveal sensitive data)
- 8 iobuf filter functions
- 16 iobuf stuff
- 32 memory allocation stuff
- 64 caching
- 128 show memory statistics at exit
- 256 trust verification stuff
+ For more options/commands see the man page or use "gpg --help".
Other Notes
-----------
- This is work in progress, so you may find duplicated code fragments,
- ugly data structures, weird usage of filenames and other things.
The primary FTP site is "ftp://ftp.gnupg.org/pub/gcrypt/"
The primary WWW page is "http://www.gnupg.org"
- If you like, send your keys to <gnupg-keys@isil.d.shuttle.de>; use
- "gpg --export --armor | mail gnupg-keys@isil.d.shuttle.de" to do this.
+ See http://www.gnugp.org/mirrors.html for a list of FTP mirrors
+ and use them if possible.
Please direct bug reports to <gnupg-bugs@gnu.org> or better
- post them to the mailing list <g10@net.lut.ac.uk> (this is a closed list,
- please subscribe before posting, see above (~line 33)).
-
+ post them to the mailing list <g10@net.lut.ac.uk> (this is a
+ closed list - subscribe before posting, see above (~line 33)).
+ Please direct questions about GnuPG to the mailing list or
+ one of the pgp newsgroups; this gives me more time to improve
+ GnuPG. Commercial support for GnuPG will be availabe soon.
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v0.4.4 (GNU/Linux)
-Comment: For info finger gcrypt@ftp.guug.de
+ Have fun and remember: Echelon is looking at you kid.
-iQB1AwUBNlXAUh0Z9MEMmFelAQFmhwL/RfW9WxAMTh/edDy0yGTJjDgo7d/Kfmtq
-8C0LJ4b2M0py1ctW6jZyiQsYtvkrttKiTYXGtRoIzVFWX2hqABKPCTHzOeXQEOSu
-ro5fnRwsuj9cRxhH8lpN+diY+m1E5Fu3
-=sciv
------END PGP SIGNATURE-----
diff --git a/TODO b/TODO
index 96dcaab23..f37ed3d4c 100644
--- a/TODO
+++ b/TODO
@@ -1,49 +1,48 @@
+Bugs
+----
+ * clearsig: keep lineendings as they are. Remember that trailings
+ blanks are not hashed. Funny: pgp263in works fine even with
+ a source file with CR,LF but GnuPG and pgp263in has problems
+ if the clearsign has been created by pgp263ia.
+ Needs more investigation - anyone?
+Important
+----------
* Check revocation and expire stuff. PLEASE: THIS MUST BE TESTED!
- * Escape "From "
-
* Check calculation of key validity. PLEASE: IT IS IMPORTED THAT
THIS GET TESTED.
- * preferences of hash algorithms are not yet used.
+ * It has been reported that lockfiles are not removed in all cases.
+ cleanup is done with atexit() and all signals trigger exit() -
+ anything wrong with this?
* I noticed, that we sometimes have only 3 items in a trustrecord, but
a next pointer ro more records - check wehther the reuse code really
works. Maybe this is the reason for the "Hmmm public key lost"
- * clearsig: keep lineendings as they are. Remember that trailings
- blanks are not hashed.
-
- * should we flush the getkey.c caches while doing an import?
-
- * We need a maintainence pass over the trustdb which flags
- signatures as expired if the key used to make the signature has
- expired. Maybe it is a good idea to store the exiration time
- in the key record of the trustdb.
+Needed
+------
+ * remove more "Fixmes"
- * write a tool to extract selected keys from a file.
+ * Replace Blowfish by Twofish and add the new encrypted packet typ
+ which has a MACing option (append SHA1 hash to the plaintext and
+ encrypt this all) - We need an identifier for Twofish to put this
+ one into the cipher preferences.
+Nice to have
+------------
+ * preferences of hash algorithms are not yet used.
* new menu to delete signatures and list signature in menu
-
* Replace the SIGUSR1 stuff by semaphores to avoid loss of a signal.
or use POSIX.4 realtime signals.
-
* add test cases for invalid data (scrambled armor or other random data)
-
- * rewrite --list-packets or put it into another tool.
-
+ * add checking of armor trailers
* Burn the buffers used by fopen(), or use read(2). Does this
really make sense?
-
- * Change the buffering to a mbuf like scheme? Need it for PSST anyway;
- see Michael's proposal.
- * add checking of armor trailers
- * remove all "Fixmes" ;-)
-
* change the fake_data stuff to mpi_set_opaque
- * Replace Blowfish by Twofish
-
- * Work on the library
+Minor Bugs
+----------
+ * md_start_debug used to crash at pgm termination.
diff --git a/VERSION b/VERSION
index 911e57f05..6f9a81767 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.4.5a
+0.4.5b
diff --git a/cipher/blowfish.c b/cipher/blowfish.c
index f5c29c6aa..fdc4c4bfb 100644
--- a/cipher/blowfish.c
+++ b/cipher/blowfish.c
@@ -1,589 +1,589 @@
/* blowfish.c - Blowfish encryption
* Copyright (C) 1998 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 336 ff.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 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 "util.h"
#include "types.h"
#include "blowfish.h"
#define CIPHER_ALGO_BLOWFISH 4 /* blowfish 128 bit key */
#define CIPHER_ALGO_BLOWFISH160 42 /* blowfish 160 bit key (not in OpenPGP)*/
#define FNCCAST_SETKEY(f) (int(*)(void*, byte*, unsigned))(f)
#define FNCCAST_CRYPT(f) (void(*)(void*, byte*, byte*))(f)
#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
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
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];
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
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
selftest()
{
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 ) )
log_error("wrong blowfish encryption\n");
decrypt_block( &c, buffer, buffer );
if( memcmp( buffer, plain, 8 ) )
log_bug("blowfish failed\n");
bf_setkey( &c, key3, 8 );
encrypt_block( &c, buffer, plain3 );
if( memcmp( buffer, cipher3, 8 ) )
log_error("wrong blowfish encryption (3)\n");
decrypt_block( &c, buffer, buffer );
if( memcmp( buffer, plain3, 8 ) )
log_bug("blowfish failed (3)\n");
}
static int
bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
{
int i, j;
u32 data, datal, datar;
static int initialized;
if( !initialized ) {
initialized = 1;
selftest();
}
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 ) {
encrypt( c, &datal, &datar );
c->p[i] = datal;
c->p[i+1] = datar;
}
for(i=0; i < 256; i += 2 ) {
encrypt( c, &datal, &datar );
c->s0[i] = datal;
c->s0[i+1] = datar;
}
for(i=0; i < 256; i += 2 ) {
encrypt( c, &datal, &datar );
c->s1[i] = datal;
c->s1[i+1] = datar;
}
for(i=0; i < 256; i += 2 ) {
encrypt( c, &datal, &datar );
c->s2[i] = datal;
c->s2[i+1] = datar;
}
for(i=0; i < 256; i += 2 ) {
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;
}
/****************
* 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 = algo == CIPHER_ALGO_BLOWFISH ? 128 : 160;
*blocksize = BLOWFISH_BLOCKSIZE;
*contextsize = sizeof(BLOWFISH_context);
*r_setkey = FNCCAST_SETKEY(bf_setkey);
*r_encrypt= FNCCAST_CRYPT(encrypt_block);
*r_decrypt= FNCCAST_CRYPT(decrypt_block);
if( algo == CIPHER_ALGO_BLOWFISH )
return "BLOWFISH";
if( algo == CIPHER_ALGO_BLOWFISH160 )
return "BLOWFISH160";
return NULL;
}
diff --git a/cipher/blowfish.h b/cipher/blowfish.h
index d3848aae8..b1d65f36c 100644
--- a/cipher/blowfish.h
+++ b/cipher/blowfish.h
@@ -1,34 +1,34 @@
/* blowfish.h
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 (**setkey)( void *c, byte *key, unsigned keylen ),
void (**encrypt)( void *c, byte *outbuf, byte *inbuf ),
void (**decrypt)( void *c, byte *outbuf, byte *inbuf )
);
#endif /*G10_BLOWFISH_H*/
diff --git a/cipher/cast5.c b/cipher/cast5.c
index 64866ba7f..279838fa3 100644
--- a/cipher/cast5.c
+++ b/cipher/cast5.c
@@ -1,614 +1,614 @@
/* cast5.c - CAST5 cipher (RFC2144)
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <assert.h>
#include "util.h"
#include "types.h"
#include "cast5.h"
#define CIPHER_ALGO_CAST5 3
#define FNCCAST_SETKEY(f) (int(*)(void*, byte*, unsigned))(f)
#define FNCCAST_CRYPT(f) (void(*)(void*, byte*, byte*))(f)
#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
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
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
selftest()
{
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 ) )
log_error("wrong cast5-128 encryption\n");
decrypt_block( &c, buffer, buffer );
if( memcmp( buffer, plain, 8 ) )
log_bug("cast5-128 failed\n");
#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 ) )
log_bug("cast5-128 maintenance test failed\n");
}
#endif
}
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
cast_setkey( CAST5_context *c, byte *key, unsigned keylen )
{
static int initialized;
int i;
u32 x[4];
u32 z[4];
u32 k[16];
if( !initialized ) {
initialized = 1;
selftest();
}
assert(keylen==16);
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;
}
/****************
* 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);
*r_setkey = FNCCAST_SETKEY(cast_setkey);
*r_encrypt= FNCCAST_CRYPT(encrypt_block);
*r_decrypt= FNCCAST_CRYPT(decrypt_block);
if( algo == CIPHER_ALGO_CAST5 )
return "CAST5";
return NULL;
}
diff --git a/cipher/cast5.h b/cipher/cast5.h
index ea6fa9e43..df7f16519 100644
--- a/cipher/cast5.h
+++ b/cipher/cast5.h
@@ -1,33 +1,33 @@
/* cast5.h
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 (**setkey)( void *c, byte *key, unsigned keylen ),
void (**encrypt)( void *c, byte *outbuf, byte *inbuf ),
void (**decrypt)( void *c, byte *outbuf, byte *inbuf )
);
#endif /*G10_CAST5_H*/
diff --git a/cipher/cipher.c b/cipher/cipher.c
index 95c4b70df..f27eec397 100644
--- a/cipher/cipher.c
+++ b/cipher/cipher.c
@@ -1,574 +1,574 @@
/* cipher.c - cipher dispatcher
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
*/
#define DEFINES_CIPHER_HANDLE 1
#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 10
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];
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 );
byte context[1];
};
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(); }
/****************
* Put the static entries into the table.
*/
static void
setup_cipher_table()
{
int i;
i = 0;
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++;
cipher_table[i].algo = CIPHER_ALGO_BLOWFISH160;
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_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++;
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()
{
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 ) {
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;
do {
for(i=0; (s=cipher_table[i].name); i++ )
if( !stricmp( 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;
}
/****************
* 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 )
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 )
: m_alloc_clear( sizeof *hd + cipher_table[i].contextsize );
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( algo == CIPHER_ALGO_DUMMY )
hd->mode = CIPHER_MODE_DUMMY;
else if( mode == CIPHER_MODE_AUTO_CFB ) {
if( algo == CIPHER_ALGO_BLOWFISH160 || algo >= 100 )
hd->mode = CIPHER_MODE_CFB;
else
hd->mode = CIPHER_MODE_PHILS_CFB;
}
else
hd->mode = mode;
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, key, keylen );
}
void
cipher_setiv( CIPHER_HANDLE c, const byte *iv )
{
if( iv )
memcpy( c->iv, iv, c->blocksize );
else
memset( c->iv, 0, c->blocksize );
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, 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, outbuf, inbuf );
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->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->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->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->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%8));
do_ecb_encrypt(c, outbuf, inbuf, nbytes/8 );
break;
case CIPHER_MODE_CFB:
case CIPHER_MODE_PHILS_CFB:
do_cfb_encrypt(c, outbuf, inbuf, nbytes );
break;
case CIPHER_MODE_DUMMY:
if( inbuf != outbuf )
memmove( outbuf, inbuf, nbytes );
break;
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%8));
do_ecb_decrypt(c, outbuf, inbuf, nbytes/8 );
break;
case CIPHER_MODE_CFB:
case CIPHER_MODE_PHILS_CFB:
do_cfb_decrypt(c, outbuf, inbuf, nbytes );
break;
case CIPHER_MODE_DUMMY:
if( inbuf != outbuf )
memmove( outbuf, inbuf, nbytes );
break;
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;
}
}
diff --git a/cipher/des.c b/cipher/des.c
index f730568e0..f7187c0a1 100644
--- a/cipher/des.c
+++ b/cipher/des.c
@@ -1,902 +1,902 @@
/* des.c - DES and Triple-DES encryption/decryption Algorithm
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* Please see below for more legal information!
*
* According to the definition of DES in FIPS PUB 46-2 from December 1993.
* For a description of triple encryption, see:
* Bruce Schneier: Applied Cryptography. Second Edition.
* John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
*/
/*
* Written by Michael Roth <mroth@nessie.de>, September 1998
*/
/*
* U S A G E
* ===========
*
* For DES or Triple-DES encryption/decryption you must initialize a proper
* encryption context with a key.
*
* A DES key is 64bit wide but only 56bits of the key are used. The remaining
* bits are parity bits and they will _not_ checked in this implementation, but
* simply ignored.
*
* For Tripple-DES you could use either two 64bit keys or three 64bit keys.
* The parity bits will _not_ checked, too.
*
* After initializing a context with a key you could use this context to
* encrypt or decrypt data in 64bit blocks in Electronic Codebook Mode.
*
* (In the examples below the slashes at the beginning and ending of comments
* are omited.)
*
* DES Example
* -----------
* unsigned char key[8];
* unsigned char plaintext[8];
* unsigned char ciphertext[8];
* unsigned char recoverd[8];
* des_ctx context;
*
* * Fill 'key' and 'plaintext' with some data *
* ....
*
* * Set up the DES encryption context *
* des_setkey(context, key);
*
* * Encrypt the plaintext *
* des_ecb_encrypt(context, plaintext, ciphertext);
*
* * To recover the orginal plaintext from ciphertext use: *
* des_ecb_decrypt(context, ciphertext, recoverd);
*
*
* Triple-DES Example
* ------------------
* unsigned char key1[8];
* unsigned char key2[8];
* unsigned char key3[8];
* unsigned char plaintext[8];
* unsigned char ciphertext[8];
* unsigned char recoverd[8];
* tripledes_ctx context;
*
* * If you would like to use two 64bit keys, fill 'key1' and'key2'
* then setup the encryption context: *
* tripledes_set2keys(context, key1, key2);
*
* * To use three 64bit keys with Triple-DES use: *
* tripledes_set3keys(context, key1, key2, key3);
*
* * Encrypting plaintext with Triple-DES *
* tripledes_ecb_encrypt(context, plaintext, ciphertext);
*
* * Decrypting ciphertext to recover the plaintext with Triple-DES *
* tripledes_ecb_decrypt(context, ciphertext, recoverd);
*
*
* Selftest
* --------
* char *error_msg;
*
* * To perform a selftest of this DES/Triple-DES implementation use the
* function selftest(). It will return an error string if their are
* some problems with this library. *
*
* if ( (error_msg = selftest()) )
* {
* fprintf(stderr, "An error in the DES/Tripple-DES implementation occured: %s\n", error_msg);
* abort();
* }
*/
#include <config.h>
#include <string.h> /* memcpy, memcmp */
#include <assert.h>
#include "types.h" /* for byte and u32 typedefs */
#include "util.h" /* for log_fatal() */
#include "des.h"
/* Some defines/checks to support standalone modules */
#ifndef CIPHER_ALGO_3DES
#define CIPHER_ALGO_3DES 2
#elif CIPHER_ALGO_3DES != 2
#error CIPHER_ALGO_3DES is defined to a wrong value.
#endif
#ifndef G10ERR_WEAK_KEY
#define G10ERR_WEAK_KEY 43
#elif G10ERR_WEAK_KEY != 43
#error G10ERR_WEAK_KEY is defined to a wrong value.
#endif
#ifndef G10ERR_WRONG_KEYLEN
#define G10ERR_WRONG_KEYLEN 44
#elif G10ERR_WRONG_KEYLEN != 44
#error G10ERR_WRONG_KEYLEN is defined to a wrong value.
#endif
/* Macros used by the info function. */
#define FNCCAST_SETKEY(f) ((int(*)(void*, byte*, unsigned))(f))
#define FNCCAST_CRYPT(f) ((void(*)(void*, byte*, byte*))(f))
/*
* Encryption/Decryption context of DES
*/
typedef struct _des_ctx
{
u32 encrypt_subkeys[32];
u32 decrypt_subkeys[32];
}
des_ctx[1];
/*
* Encryption/Decryption context of Triple-DES
*/
typedef struct _tripledes_ctx
{
u32 encrypt_subkeys[96];
u32 decrypt_subkeys[96];
}
tripledes_ctx[1];
static void des_key_schedule (const byte *, u32 *);
static int des_setkey (struct _des_ctx *, const byte *);
static int des_ecb_crypt (struct _des_ctx *, const byte *, byte *, int);
static int tripledes_set2keys (struct _tripledes_ctx *, const byte *, const byte *);
static int tripledes_set3keys (struct _tripledes_ctx *, const byte *, const byte *, const byte *);
static int tripledes_ecb_crypt (struct _tripledes_ctx *, const byte *, byte *, int);
static int is_weak_key ( const byte *key );
static const char *selftest (void);
/*
* The s-box values are permuted according to the 'primitive function P'
*/
static u32 sbox1[64] =
{
0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000,
0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002,
0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202,
0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000,
0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200,
0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202,
0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200,
0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002
};
static u32 sbox2[64] =
{
0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010,
0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010,
0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000,
0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010,
0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000,
0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000,
0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010,
0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000
};
static u32 sbox3[64] =
{
0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100,
0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104,
0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104,
0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000,
0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000,
0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004,
0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004,
0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100
};
static u32 sbox4[64] =
{
0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000,
0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000,
0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040,
0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040,
0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000,
0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040,
0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040,
0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040
};
static u32 sbox5[64] =
{
0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000,
0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000,
0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080,
0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080,
0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080,
0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000,
0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000,
0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080
};
static u32 sbox6[64] =
{
0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000,
0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008,
0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008,
0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000,
0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008,
0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000,
0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008,
0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008
};
static u32 sbox7[64] =
{
0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400,
0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401,
0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001,
0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400,
0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001,
0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400,
0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401,
0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001
};
static u32 sbox8[64] =
{
0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000,
0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020,
0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800,
0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000,
0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820,
0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820,
0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000,
0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800
};
/*
* These two tables are part of the 'permuted choice 1' function.
* In this implementation several speed improvements are done.
*/
u32 leftkey_swap[16] =
{
0x00000000, 0x00000001, 0x00000100, 0x00000101,
0x00010000, 0x00010001, 0x00010100, 0x00010101,
0x01000000, 0x01000001, 0x01000100, 0x01000101,
0x01010000, 0x01010001, 0x01010100, 0x01010101
};
u32 rightkey_swap[16] =
{
0x00000000, 0x01000000, 0x00010000, 0x01010000,
0x00000100, 0x01000100, 0x00010100, 0x01010100,
0x00000001, 0x01000001, 0x00010001, 0x01010001,
0x00000101, 0x01000101, 0x00010101, 0x01010101,
};
/*
* Numbers of left shifts per round for encryption subkey schedule
* To calculate the decryption key scheduling we just reverse the
* ordering of the subkeys so we can omit the table for decryption
* subkey schedule.
*/
static byte encrypt_rotate_tab[16] =
{
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
};
/*
* Table with weak DES keys sorted in ascending order.
* In DES their are 64 known keys wich are weak. They are weak
* because they produce only one, two or four different
* subkeys in the subkey scheduling process.
* The keys in this table have all their parity bits cleared.
*/
static byte weak_keys[64][8] =
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e },
{ 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0 }, { 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe },
{ 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e }, { 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00 },
{ 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe }, { 0x00, 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0 },
{ 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0 }, { 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe },
{ 0x00, 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00 }, { 0x00, 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e },
{ 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe }, { 0x00, 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0 },
{ 0x00, 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e }, { 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00 },
{ 0x0e, 0x0e, 0x0e, 0x0e, 0xf0, 0xf0, 0xf0, 0xf0 }, { 0x1e, 0x00, 0x00, 0x1e, 0x0e, 0x00, 0x00, 0x0e },
{ 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00 }, { 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0, 0xfe },
{ 0x1e, 0x00, 0xfe, 0xe0, 0x0e, 0x00, 0xfe, 0xf0 }, { 0x1e, 0x1e, 0x00, 0x00, 0x0e, 0x0e, 0x00, 0x00 },
{ 0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e }, { 0x1e, 0x1e, 0xe0, 0xe0, 0x0e, 0x0e, 0xf0, 0xf0 },
{ 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe, 0xfe }, { 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00, 0xfe },
{ 0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0 }, { 0x1e, 0xe0, 0xe0, 0x1e, 0x0e, 0xf0, 0xf0, 0x0e },
{ 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0, 0xfe, 0x00 }, { 0x1e, 0xfe, 0x00, 0xe0, 0x0e, 0xfe, 0x00, 0xf0 },
{ 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe }, { 0x1e, 0xfe, 0xe0, 0x00, 0x0e, 0xfe, 0xf0, 0x00 },
{ 0x1e, 0xfe, 0xfe, 0x1e, 0x0e, 0xfe, 0xfe, 0x0e }, { 0xe0, 0x00, 0x00, 0xe0, 0xf0, 0x00, 0x00, 0xf0 },
{ 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e, 0xfe }, { 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00 },
{ 0xe0, 0x00, 0xfe, 0x1e, 0xf0, 0x00, 0xfe, 0x0e }, { 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00, 0xfe },
{ 0xe0, 0x1e, 0x1e, 0xe0, 0xf0, 0x0e, 0x0e, 0xf0 }, { 0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e },
{ 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e, 0xfe, 0x00 }, { 0xe0, 0xe0, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00 },
{ 0xe0, 0xe0, 0x1e, 0x1e, 0xf0, 0xf0, 0x0e, 0x0e }, { 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe, 0xfe },
{ 0xe0, 0xfe, 0x00, 0x1e, 0xf0, 0xfe, 0x00, 0x0e }, { 0xe0, 0xfe, 0x1e, 0x00, 0xf0, 0xfe, 0x0e, 0x00 },
{ 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe }, { 0xe0, 0xfe, 0xfe, 0xe0, 0xf0, 0xfe, 0xfe, 0xf0 },
{ 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00, 0xfe }, { 0xfe, 0x00, 0x1e, 0xe0, 0xfe, 0x00, 0x0e, 0xf0 },
{ 0xfe, 0x00, 0xe0, 0x1e, 0xfe, 0x00, 0xf0, 0x0e }, { 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00 },
{ 0xfe, 0x1e, 0x00, 0xe0, 0xfe, 0x0e, 0x00, 0xf0 }, { 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e, 0xfe },
{ 0xfe, 0x1e, 0xe0, 0x00, 0xfe, 0x0e, 0xf0, 0x00 }, { 0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e },
{ 0xfe, 0xe0, 0x00, 0x1e, 0xfe, 0xf0, 0x00, 0x0e }, { 0xfe, 0xe0, 0x1e, 0x00, 0xfe, 0xf0, 0x0e, 0x00 },
{ 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0, 0xfe }, { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0 },
{ 0xfe, 0xfe, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x00 }, { 0xfe, 0xfe, 0x1e, 0x1e, 0xfe, 0xfe, 0x0e, 0x0e },
{ 0xfe, 0xfe, 0xe0, 0xe0, 0xfe, 0xfe, 0xf0, 0xf0 }, { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe }
};
/*
* Macro to swap bits across two words
*/
#define DO_PERMUTATION(a, temp, b, offset, mask) \
temp = ((a>>offset) ^ b) & mask; \
b ^= temp; \
a ^= temp<<offset;
/*
* This performs the 'initial permutation' for the data to be encrypted or decrypted
*/
#define INITIAL_PERMUTATION(left, temp, right) \
DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f) \
DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \
DO_PERMUTATION(right, temp, left, 2, 0x33333333) \
DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \
DO_PERMUTATION(left, temp, right, 1, 0x55555555)
/*
* The 'inverse initial permutation'
*/
#define FINAL_PERMUTATION(left, temp, right) \
DO_PERMUTATION(left, temp, right, 1, 0x55555555) \
DO_PERMUTATION(right, temp, left, 8, 0x00ff00ff) \
DO_PERMUTATION(right, temp, left, 2, 0x33333333) \
DO_PERMUTATION(left, temp, right, 16, 0x0000ffff) \
DO_PERMUTATION(left, temp, right, 4, 0x0f0f0f0f)
/*
* A full DES round including 'expansion function', 'sbox substitution'
* and 'primitive function P' but without swapping the left and right word.
*/
#define DES_ROUND(from, to, work, subkey) \
work = ((from<<1) | (from>>31)) ^ *subkey++; \
to ^= sbox8[ work & 0x3f ]; \
to ^= sbox6[ (work>>8) & 0x3f ]; \
to ^= sbox4[ (work>>16) & 0x3f ]; \
to ^= sbox2[ (work>>24) & 0x3f ]; \
work = ((from>>3) | (from<<29)) ^ *subkey++; \
to ^= sbox7[ work & 0x3f ]; \
to ^= sbox5[ (work>>8) & 0x3f ]; \
to ^= sbox3[ (work>>16) & 0x3f ]; \
to ^= sbox1[ (work>>24) & 0x3f ];
/*
* Macros to convert 8 bytes from/to 32bit words
*/
#define READ_64BIT_DATA(data, left, right) \
left = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; \
right = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7];
#define WRITE_64BIT_DATA(data, left, right) \
data[0] = (left >> 24) &0xff; data[1] = (left >> 16) &0xff; \
data[2] = (left >> 8) &0xff; data[3] = left &0xff; \
data[4] = (right >> 24) &0xff; data[5] = (right >> 16) &0xff; \
data[6] = (right >> 8) &0xff; data[7] = right &0xff;
/*
* Handy macros for encryption and decryption of data
*/
#define des_ecb_encrypt(ctx, from, to) des_ecb_crypt(ctx, from, to, 0)
#define des_ecb_decrypt(ctx, from, to) des_ecb_crypt(ctx, from, to, 1)
#define tripledes_ecb_encrypt(ctx, from, to) tripledes_ecb_crypt(ctx, from, to, 0)
#define tripledes_ecb_decrypt(ctx, from, to) tripledes_ecb_crypt(ctx, from, to, 1)
/*
* des_key_schedule(): Calculate 16 subkeys pairs (even/odd) for
* 16 encryption rounds.
* To calculate subkeys for decryption the caller
* have to reorder the generated subkeys.
*
* rawkey: 8 Bytes of key data
* subkey: Array of at least 32 u32s. Will be filled
* with calculated subkeys.
*
*/
static void
des_key_schedule (const byte * rawkey, u32 * subkey)
{
u32 left, right, work;
int round;
READ_64BIT_DATA (rawkey, left, right)
DO_PERMUTATION (right, work, left, 4, 0x0f0f0f0f)
DO_PERMUTATION (right, work, left, 0, 0x10101010)
left = (leftkey_swap[(left >> 0) & 0xf] << 3) | (leftkey_swap[(left >> 8) & 0xf] << 2)
| (leftkey_swap[(left >> 16) & 0xf] << 1) | (leftkey_swap[(left >> 24) & 0xf])
| (leftkey_swap[(left >> 5) & 0xf] << 7) | (leftkey_swap[(left >> 13) & 0xf] << 6)
| (leftkey_swap[(left >> 21) & 0xf] << 5) | (leftkey_swap[(left >> 29) & 0xf] << 4);
left &= 0x0fffffff;
right = (rightkey_swap[(right >> 1) & 0xf] << 3) | (rightkey_swap[(right >> 9) & 0xf] << 2)
| (rightkey_swap[(right >> 17) & 0xf] << 1) | (rightkey_swap[(right >> 25) & 0xf])
| (rightkey_swap[(right >> 4) & 0xf] << 7) | (rightkey_swap[(right >> 12) & 0xf] << 6)
| (rightkey_swap[(right >> 20) & 0xf] << 5) | (rightkey_swap[(right >> 28) & 0xf] << 4);
right &= 0x0fffffff;
for (round = 0; round < 16; ++round)
{
left = ((left << encrypt_rotate_tab[round]) | (left >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff;
right = ((right << encrypt_rotate_tab[round]) | (right >> (28 - encrypt_rotate_tab[round]))) & 0x0fffffff;
*subkey++ = ((left << 4) & 0x24000000)
| ((left << 28) & 0x10000000)
| ((left << 14) & 0x08000000)
| ((left << 18) & 0x02080000)
| ((left << 6) & 0x01000000)
| ((left << 9) & 0x00200000)
| ((left >> 1) & 0x00100000)
| ((left << 10) & 0x00040000)
| ((left << 2) & 0x00020000)
| ((left >> 10) & 0x00010000)
| ((right >> 13) & 0x00002000)
| ((right >> 4) & 0x00001000)
| ((right << 6) & 0x00000800)
| ((right >> 1) & 0x00000400)
| ((right >> 14) & 0x00000200)
| (right & 0x00000100)
| ((right >> 5) & 0x00000020)
| ((right >> 10) & 0x00000010)
| ((right >> 3) & 0x00000008)
| ((right >> 18) & 0x00000004)
| ((right >> 26) & 0x00000002)
| ((right >> 24) & 0x00000001);
*subkey++ = ((left << 15) & 0x20000000)
| ((left << 17) & 0x10000000)
| ((left << 10) & 0x08000000)
| ((left << 22) & 0x04000000)
| ((left >> 2) & 0x02000000)
| ((left << 1) & 0x01000000)
| ((left << 16) & 0x00200000)
| ((left << 11) & 0x00100000)
| ((left << 3) & 0x00080000)
| ((left >> 6) & 0x00040000)
| ((left << 15) & 0x00020000)
| ((left >> 4) & 0x00010000)
| ((right >> 2) & 0x00002000)
| ((right << 8) & 0x00001000)
| ((right >> 14) & 0x00000808)
| ((right >> 9) & 0x00000400)
| ((right) & 0x00000200)
| ((right << 7) & 0x00000100)
| ((right >> 7) & 0x00000020)
| ((right >> 3) & 0x00000011)
| ((right << 2) & 0x00000004)
| ((right >> 21) & 0x00000002);
}
}
/*
* Fill a DES context with subkeys calculated from a 64bit key.
* Does not check parity bits, but simply ignore them.
* Does not check for weak keys.
*/
static int
des_setkey (struct _des_ctx *ctx, const byte * key)
{
int i;
des_key_schedule (key, ctx->encrypt_subkeys);
for(i=0; i<32; i+=2)
{
ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i];
ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i];
}
return 0;
}
/*
* Electronic Codebook Mode DES encryption/decryption of data according
* to 'mode'.
*/
static int
des_ecb_crypt (struct _des_ctx *ctx, const byte * from, byte * to, int mode)
{
u32 left, right, work;
u32 *keys;
keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys;
READ_64BIT_DATA (from, left, right)
INITIAL_PERMUTATION (left, work, right)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
FINAL_PERMUTATION (right, work, left)
WRITE_64BIT_DATA (to, right, left)
return 0;
}
/*
* Fill a Triple-DES context with subkeys calculated from two 64bit keys.
* Does not check the parity bits of the keys, but simply ignore them.
* Does not check for weak keys.
*/
static int
tripledes_set2keys (struct _tripledes_ctx *ctx,
const byte * key1,
const byte * key2)
{
int i;
des_key_schedule (key1, ctx->encrypt_subkeys);
des_key_schedule (key2, &(ctx->decrypt_subkeys[32]));
for(i=0; i<32; i+=2)
{
ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[30-i];
ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[31-i];
ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i];
ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i];
ctx->encrypt_subkeys[i+64] = ctx->encrypt_subkeys[i];
ctx->encrypt_subkeys[i+65] = ctx->encrypt_subkeys[i+1];
ctx->decrypt_subkeys[i+64] = ctx->decrypt_subkeys[i];
ctx->decrypt_subkeys[i+65] = ctx->decrypt_subkeys[i+1];
}
return 0;
}
/*
* Fill a Triple-DES context with subkeys calculated from three 64bit keys.
* Does not check the parity bits of the keys, but simply ignore them.
* Does not check for weak keys.
*/
static int
tripledes_set3keys (struct _tripledes_ctx *ctx,
const byte * key1,
const byte * key2,
const byte * key3)
{
int i;
des_key_schedule (key1, ctx->encrypt_subkeys);
des_key_schedule (key2, &(ctx->decrypt_subkeys[32]));
des_key_schedule (key3, &(ctx->encrypt_subkeys[64]));
for(i=0; i<32; i+=2)
{
ctx->decrypt_subkeys[i] = ctx->encrypt_subkeys[94-i];
ctx->decrypt_subkeys[i+1] = ctx->encrypt_subkeys[95-i];
ctx->encrypt_subkeys[i+32] = ctx->decrypt_subkeys[62-i];
ctx->encrypt_subkeys[i+33] = ctx->decrypt_subkeys[63-i];
ctx->decrypt_subkeys[i+64] = ctx->encrypt_subkeys[30-i];
ctx->decrypt_subkeys[i+65] = ctx->encrypt_subkeys[31-i];
}
return 0;
}
/*
* Electronic Codebook Mode Triple-DES encryption/decryption of data according to 'mode'.
* Sometimes this mode is named 'EDE' mode (Encryption-Decryption-Encryption).
*/
static int
tripledes_ecb_crypt (struct _tripledes_ctx *ctx, const byte * from, byte * to, int mode)
{
u32 left, right, work;
u32 *keys;
keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys;
READ_64BIT_DATA (from, left, right)
INITIAL_PERMUTATION (left, work, right)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys)
DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys)
DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys)
DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys)
DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys)
DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys)
DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys)
DES_ROUND (left, right, work, keys) DES_ROUND (right, left, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
DES_ROUND (right, left, work, keys) DES_ROUND (left, right, work, keys)
FINAL_PERMUTATION (right, work, left)
WRITE_64BIT_DATA (to, right, left)
return 0;
}
/*
* Check whether the 8 byte key is weak.
* Dose not check the parity bits of the key but simple ignore them.
*/
static int
is_weak_key ( const byte *key )
{
byte work[8];
int i, left, right, middle, cmp_result;
/* clear parity bits */
for(i=0; i<8; ++i)
work[i] = key[i] & 0xfe;
/* binary search in the weak key table */
left = 0;
right = 63;
while(1)
{
middle = (left + right) / 2;
if ( !(cmp_result=memcmp(work, weak_keys[middle], 8)) )
return -1;
if ( left == right )
break;
if ( cmp_result > 0 )
left = middle + 1;
else
right = middle - 1;
}
return 0;
}
/*
* Performs a selftest of this DES/Triple-DES implementation.
* Returns an string with the error text on failure.
* Returns NULL if all is ok.
*/
static const char *
selftest (void)
{
/*
* Check if 'u32' is really 32 bits wide. This DES / 3DES implementation
* need this.
*/
if (sizeof (u32) != 4)
return "Wrong word size for DES configured.";
/*
* DES Maintenance Test
*/
{
int i;
byte key[8] =
{0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
byte input[8] =
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
byte result[8] =
{0x24, 0x6e, 0x9d, 0xb9, 0xc5, 0x50, 0x38, 0x1a};
byte temp1[8], temp2[8], temp3[8];
des_ctx des;
for (i = 0; i < 64; ++i)
{
des_setkey (des, key);
des_ecb_encrypt (des, input, temp1);
des_ecb_encrypt (des, temp1, temp2);
des_setkey (des, temp2);
des_ecb_decrypt (des, temp1, temp3);
memcpy (key, temp3, 8);
memcpy (input, temp1, 8);
}
if (memcmp (temp3, result, 8))
return "DES maintenance test failed.";
}
/*
* Triple-DES test (Do somebody known on official test?)
*
* FIXME: This test doesn't use tripledes_set3keys() !
*/
{
int i;
byte input[8] =
{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
byte key1[8] =
{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};
byte key2[8] =
{0x11, 0x22, 0x33, 0x44, 0xff, 0xaa, 0xcc, 0xdd};
byte result[8] =
{0x7b, 0x38, 0x3b, 0x23, 0xa2, 0x7d, 0x26, 0xd3};
tripledes_ctx des3;
for (i = 0; i < 16; ++i)
{
tripledes_set2keys (des3, key1, key2);
tripledes_ecb_encrypt (des3, input, key1);
tripledes_ecb_decrypt (des3, input, key2);
tripledes_set3keys (des3, key1, input, key2);
tripledes_ecb_encrypt (des3, input, input);
}
if (memcmp (input, result, 8))
return "TRIPLE-DES test failed.";
}
/*
* Check the weak key detection. We simply assume the table with
* weak keys is ok and check every key in the table if it is
* detected... (This test is a little bit stupid)
*/
{
int i;
for (i = 0; i < 64; ++i)
if (!is_weak_key(weak_keys[i]))
return "DES weak key detection failed";
}
return 0;
}
static int
do_tripledes_setkey ( struct _tripledes_ctx *ctx, byte *key, unsigned keylen )
{
if( keylen != 24 )
return G10ERR_WRONG_KEYLEN;
tripledes_set3keys ( ctx, key, key+8, key+16);
if( is_weak_key( key ) || is_weak_key( key+8 ) || is_weak_key( key+16 ) )
return G10ERR_WEAK_KEY;
return 0;
}
static void
do_tripledes_encrypt( struct _tripledes_ctx *ctx, byte *outbuf, byte *inbuf )
{
tripledes_ecb_encrypt ( ctx, inbuf, outbuf );
}
static void
do_tripledes_decrypt( struct _tripledes_ctx *ctx, byte *outbuf, byte *inbuf )
{
tripledes_ecb_decrypt ( ctx, inbuf, outbuf );
}
/****************
* 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 *
des_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 )
)
{
static int did_selftest = 0;
if( !did_selftest ) {
const char *s = selftest();
if( s )
log_fatal("selftest failed: %s\n", s );
did_selftest = 1;
}
if( algo == CIPHER_ALGO_3DES ) {
*keylen = 192;
*blocksize = 8;
*contextsize = sizeof(struct _tripledes_ctx);
*r_setkey = FNCCAST_SETKEY(do_tripledes_setkey);
*r_encrypt= FNCCAST_CRYPT(do_tripledes_encrypt);
*r_decrypt= FNCCAST_CRYPT(do_tripledes_decrypt);
return "3DES";
}
return NULL;
}
diff --git a/cipher/des.h b/cipher/des.h
index f3b95ba65..cf2f320d8 100644
--- a/cipher/des.h
+++ b/cipher/des.h
@@ -1,34 +1,34 @@
/* des.h
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 (**setkey)( void *c, byte *key, unsigned keylen ),
void (**encrypt)( void *c, byte *outbuf, byte *inbuf ),
void (**decrypt)( void *c, byte *outbuf, byte *inbuf )
);
#endif /*G10_DES_H*/
diff --git a/cipher/dsa.c b/cipher/dsa.c
index 2d5c17344..7222df338 100644
--- a/cipher/dsa.c
+++ b/cipher/dsa.c
@@ -1,428 +1,428 @@
/* dsa.c - DSA signature scheme
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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);
/****************
* 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 nbits = mpi_get_nbits(q);
if( DBG_CIPHER )
log_debug("choosing a random k ");
for(;;) {
if( DBG_CIPHER )
fputc('.', stderr);
{ char *p = get_random_bits( nbits, 1, 1 );
mpi_set_buffer( k, p, (nbits+7)/8, 0 );
m_free(p);
/* make sure that the number is of the exact lenght */
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 */
continue; /* no */
if( !(mpi_cmp_ui( k, 0 ) > 0) ) /* check: k > 0 */
continue; /* no */
break; /* okay */
}
if( DBG_CIPHER )
fputc('\n', stderr);
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 )
fputc('.', stderr);
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 ) {
fputc('\n', stderr);
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.
*/
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.
*/
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;
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;
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;
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 *usage )
{
*npkey = 4;
*nskey = 5;
*nenc = 0;
*nsig = 2;
switch( algo ) {
case PUBKEY_ALGO_DSA: *usage = PUBKEY_USAGE_SIG; return "DSA";
default: *usage = 0; return NULL;
}
}
diff --git a/cipher/dsa.h b/cipher/dsa.h
index dda32bd6d..e5bc8c7b8 100644
--- a/cipher/dsa.h
+++ b/cipher/dsa.h
@@ -1,32 +1,32 @@
/* dsa.h - DSA signature scheme
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 *usage );
#endif /*G10_DSA_H*/
diff --git a/cipher/dynload.c b/cipher/dynload.c
index abef2da52..220f91600 100644
--- a/cipher/dynload.c
+++ b/cipher/dynload.c
@@ -1,556 +1,556 @@
/* dynload.c - load cipher extensions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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>
#endif
#include "util.h"
#include "cipher.h"
#include "dynload.h"
#ifdef DLSYM_NEEDS_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
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;
} 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 != '/' ) { /* do tilde expansion etc */
char *p ;
if( strchr(fname, '/') )
p = make_filename(fname, NULL);
else
p = make_filename(GNUPG_LIBDIR, fname, NULL);
el = m_alloc_clear( sizeof *el + strlen(p) );
strcpy(el->name, p );
m_free(p);
}
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;
el->handle = (void*)1;
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
/* make sure we are not setuid */
if( getuid() != geteuid() )
log_bug("trying to load an extension while still setuid\n");
/* 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;
}
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;
*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:
*r_get_info = ctx->sym;
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;
}
const char *
enum_gnupgext_ciphers( void **enum_context, int *algo,
size_t *keylen, size_t *blocksize, size_t *contextsize,
int (**setkey)( void *c, byte *key, unsigned keylen ),
void (**encrypt)( void *c, byte *outbuf, byte *inbuf ),
void (**decrypt)( 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:
finfo = ctx->sym;
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,
setkey, encrypt, decrypt );
if( algname ) {
ctx->r = r;
return algname;
}
}
ctx->seq2 = 0;
}
ctx->seq1 = 0;
}
ctx->r = r;
return NULL;
}
const char *
enum_gnupgext_pubkeys( void **enum_context, int *algo,
int *npkey, int *nskey, int *nenc, int *nsig, int *usage,
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 ) )
{
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:
finfo = ctx->sym;
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, usage,
generate, check_secret_key, encrypt,
decrypt, 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;
}
diff --git a/cipher/dynload.h b/cipher/dynload.h
index d107b5a0a..f22f5f3ee 100644
--- a/cipher/dynload.h
+++ b/cipher/dynload.h
@@ -1,63 +1,63 @@
/* dynload.5
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
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 (**setkey)( void *c, byte *key, unsigned keylen ),
void (**encrypt)( void *c, byte *outbuf, byte *inbuf ),
void (**decrypt)( 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 *usage,
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 ) );
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 );
#endif /*G10_CIPHER_DYNLOAD_H*/
diff --git a/cipher/elgamal.c b/cipher/elgamal.c
index b330ccff0..9a9b35629 100644
--- a/cipher/elgamal.c
+++ b/cipher/elgamal.c
@@ -1,551 +1,551 @@
/* elgamal.c - ElGamal Public Key encryption
* Copyright (C) 1998 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.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 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
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);
}
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 nbits = mpi_get_nbits(p);
if( DBG_CIPHER )
log_debug("choosing a random k ");
mpi_sub_ui( p_1, p, 1);
for(;;) {
if( DBG_CIPHER )
fputc('.', stderr);
{ char *p = get_random_bits( nbits, 1, 1 );
mpi_set_buffer( k, p, (nbits+7)/8, 0 );
m_free(p);
/* make sure that the number is of the exact lenght */
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, p_1 ) < 0) ) /* check: k < (p-1) */
continue; /* no */
if( !(mpi_cmp_ui( k, 0 ) > 0) ) /* check: k > 0 */
continue; /* no */
if( mpi_gcd( temp, k, p_1 ) )
break; /* okay, k is relatively prime to (p-1) */
}
if( DBG_CIPHER )
fputc('\n', stderr);
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 nbits, MPI **ret_factors )
{
MPI p; /* the prime */
MPI p_min1;
MPI g;
MPI x; /* the secret exponent */
MPI y;
MPI temp;
unsigned qbits;
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 );
if( nbits < 512 )
qbits = 120;
else if( nbits <= 1024 )
qbits = 160;
else if( nbits <= 2048 )
qbits = 200;
else
qbits = 240;
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.
*/
x = mpi_alloc_secure( nbits/BITS_PER_MPI_LIMB );
if( DBG_CIPHER )
log_debug("choosing a random x ");
rndbuf = NULL;
do {
if( DBG_CIPHER )
fputc('.', stderr);
if( rndbuf ) { /* change only some of the higher bits */
if( nbits < 16 ) {/* should never happen ... */
m_free(rndbuf);
rndbuf = get_random_bits( nbits, 2, 1 );
}
else {
char *r = get_random_bits( 16, 2, 1 );
memcpy(rndbuf, r, 16/8 );
m_free(r);
}
}
else
rndbuf = get_random_bits( nbits, 2, 1 );
mpi_set_buffer( x, rndbuf, (nbits+7)/8, 0 );
mpi_clear_highbit( x, nbits+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 ) {
fputc('\n', stderr);
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
encrypt(MPI a, MPI b, MPI input, ELG_public_key *pkey )
{
MPI k;
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 (FIXME: check this!)
* = ((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) )
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;
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;
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 ) );
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;
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;
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;
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
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 *usage )
{
*npkey = 3;
*nskey = 4;
*nenc = 2;
*nsig = 2;
switch( algo ) {
case PUBKEY_ALGO_ELGAMAL:
*usage = PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC;
return "ELG";
case PUBKEY_ALGO_ELGAMAL_E:
*usage = PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC;
return "ELG-E";
default: *usage = 0; return NULL;
}
}
diff --git a/cipher/elgamal.h b/cipher/elgamal.h
index 672f07704..ac708a9bb 100644
--- a/cipher/elgamal.h
+++ b/cipher/elgamal.h
@@ -1,35 +1,35 @@
/* elgamal.h
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 *usage );
#endif /*G10_ELGAMAL_H*/
diff --git a/cipher/g10c.c b/cipher/g10c.c
index 263091d49..718520057 100644
--- a/cipher/g10c.c
+++ b/cipher/g10c.c
@@ -1,44 +1,44 @@
/* g10c.c - Wrapper for cipher functions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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"
#define _g10lib_INTERNAL 1
#include "g10lib.h"
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 );
}
diff --git a/cipher/gost.c b/cipher/gost.c
index aaf2a8e17..4a527722f 100644
--- a/cipher/gost.c
+++ b/cipher/gost.c
@@ -1,76 +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.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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)
{
}
diff --git a/cipher/gost.h b/cipher/gost.h
index 4c0367477..d8e7ebfc5 100644
--- a/cipher/gost.h
+++ b/cipher/gost.h
@@ -1,46 +1,46 @@
/* gost.h
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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*/
diff --git a/cipher/md.c b/cipher/md.c
index 9a2b17920..de74c283e 100644
--- a/cipher/md.c
+++ b/cipher/md.c
@@ -1,504 +1,504 @@
/* md.c - message digest dispatcher
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
*/
#define DEFINES_MD_HANDLE 1
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "util.h"
#include "cipher.h"
#include "errors.h"
#include "dynload.h"
#include "md5.h"
#include "sha1.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 */
char context[1];
};
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;
}
/****************
* Put the static entries into the table.
*/
static void
setup_digest_list()
{
struct md_digest_list_s *r;
r = new_list_item( DIGEST_ALGO_MD5, md5_get_info );
if( r ) { r->next = digest_list; digest_list = r; }
r = new_list_item( DIGEST_ALGO_RMD160, rmd160_get_info );
if( r ) { r->next = digest_list; digest_list = r; }
r = new_list_item( DIGEST_ALGO_SHA1, sha1_get_info );
if( r ) { r->next = digest_list; digest_list = r; }
}
/****************
* Try to load all modules and return true if new modules are available
*/
static int
load_digest_modules()
{
static int done = 0;
static int initialized = 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 ) {
setup_digest_list(); /* load static modules on the first call */
initialized = 1;
return 1;
}
if( done )
return 0;
done = 1;
while( enum_gnupgext_digests( &context, &algo, &get_info ) ) {
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;
}
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( !stricmp( r->name, string ) )
return r->algo;
} while( !r && load_digest_modules() );
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_modules() );
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_modules() );
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;
hd = secure ? m_alloc_secure_clear( sizeof *hd )
: m_alloc_clear( sizeof *hd );
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_modules() );
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 )
: m_alloc( sizeof *ac + r->contextsize );
*ac = *r;
ac->next = h->list;
h->list = ac;
/* and init this instance */
(*ac->init)( &ac->context );
}
MD_HANDLE
md_copy( MD_HANDLE a )
{
MD_HANDLE b;
struct md_digest_list_s *ar, *br;
b = a->secure ? m_alloc_secure( sizeof *b )
: m_alloc( sizeof *b );
memcpy( b, a, sizeof *a );
b->list = 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 )
: m_alloc( sizeof *br + ar->contextsize );
memcpy( br, ar, sizeof(*br) + ar->contextsize );
br->next = b->list;
b->list = br;
}
return b;
}
/****************
* Reset all contexts and discard any buffered stuuf. 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 = 0;
for( r=a->list; r; r = r->next ) {
memset( r->context, 0, r->contextsize );
(*r->init)( &r->context );
}
}
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, 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, a->buffer, a->bufcount );
(*r->write)( &r->context, inbuf, inlen );
}
a->bufcount = 0;
}
void
md_final(MD_HANDLE a)
{
struct md_digest_list_s *r;
if( a->bufcount )
md_write( a, NULL, 0 );
for(r=a->list; r; r = r->next ) {
(*r->final)( &r->context );
}
}
/****************
* 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 );
}
}
else {
for(r=a->list; r; r = r->next )
if( r->algo == algo )
return (*r->read)( &r->context );
}
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, 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_modules() );
log_error("WARNING: no length for md algo %d\n", algo);
return 0;
}
/* fixme: 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_modules() );
log_bug("no asn for md algo %d\n", algo);
return NULL;
}
void
md_start_debug( MD_HANDLE md, const char *suffix )
{
static int index=0;
char buf[25];
if( md->debug ) {
log_debug("Oops: md debug already started\n");
return;
}
index++;
sprintf(buf, "dbgmd-%05d.%.10s", index, 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 ) {
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
}
diff --git a/cipher/md5.c b/cipher/md5.c
index 72fce0e22..214e13727 100644
--- a/cipher/md5.c
+++ b/cipher/md5.c
@@ -1,371 +1,371 @@
/* md5.c - MD5 Message-Digest Algorithm
* Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
*
* according to the definition of MD5 in RFC 1321 from April 1992.
* NOTE: This is *not* the same file as the one from glibc.
*
* 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.
*/
/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
-/* modified for GNUPG by <werner.koch@guug.de> */
+/* modified for GnuPG by <werner.koch@guug.de> */
/* 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 "md5.h"
#include "memory.h"
typedef struct {
u32 A,B,C,D; /* chaining variables */
u32 total[2];
u32 buflen;
char buffer[128];
} MD5_CONTEXT;
#ifdef BIG_ENDIAN_HOST
#define SWAP(n) \
(((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
#else
#define SWAP(n) (n)
#endif
/* This array contains the bytes used to pad the buffer to the next
64-byte boundary. (RFC 1321, 3.1: Step 1) */
static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
static void
md5_init( MD5_CONTEXT *ctx )
{
ctx->A = 0x67452301;
ctx->B = 0xefcdab89;
ctx->C = 0x98badcfe;
ctx->D = 0x10325476;
ctx->total[0] = ctx->total[1] = 0;
ctx->buflen = 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))
/****************
* transform n*64 bytes
*/
static void
transform( MD5_CONTEXT *ctx, const void *buffer, size_t len )
{
u32 correct_words[16];
const u32 *words = buffer;
size_t nwords = len / sizeof(u32);
const u32 *endp = words + nwords;
u32 A = ctx->A;
u32 B = ctx->B;
u32 C = ctx->C;
u32 D = ctx->D;
/* First increment the byte count. RFC 1321 specifies the possible
length of the file up to 2^64 bits. Here we only compute the
number of bytes. Do a double word increment. */
ctx->total[0] += len;
if( ctx->total[0] < len )
++ctx->total[1];
/* Process all bytes in the buffer with 64 bytes in each round of
the loop. */
while(words < endp) {
u32 *cwp = correct_words;
u32 A_save = A;
u32 B_save = B;
u32 C_save = C;
u32 D_save = D;
/* First round: using the given function, the context and a constant
the next context is computed. Because the algorithm's processing
unit is a 32-bit word, and it is determined to work on words in
little endian byte order, we perhaps have to change the byte order
before the computation. To reduce the work for the next steps
we store the swapped words in the array CORRECT_WORDS. */
#define OP(a, b, c, d, s, T) \
do \
{ \
a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
++words; \
CYCLIC (a, s); \
a += b; \
} \
while (0)
/* It is unfortunate that C does not provide an operator for
cyclic rotation. Hope the C compiler is smart enough. */
#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
/* 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);
/* For the second to fourth round we have the possibly swapped words
in CORRECT_WORDS. Redefine the macro to take an additional first
argument specifying the function to use. */
#undef OP
#define OP(f, a, b, c, d, k, s, T) \
do \
{ \
a += f (b, c, d) + correct_words[k] + T; \
CYCLIC (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);
/* Add the starting values of the context. */
A += A_save;
B += B_save;
C += C_save;
D += D_save;
}
/* 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 *ctx, const void *buffer, size_t len)
{
/* When we already have some bits in our internal buffer concatenate
both inputs first. */
if (ctx->buflen != 0)
{
size_t left_over = ctx->buflen;
size_t add = 128 - left_over > len ? len : 128 - left_over;
memcpy (&ctx->buffer[left_over], buffer, add);
ctx->buflen += add;
if (left_over + add > 64)
{
transform(ctx, ctx->buffer, (left_over + add) & ~63);
/* The regions in the following copy operation cannot overlap. */
memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
(left_over + add) & 63);
ctx->buflen = (left_over + add) & 63;
}
buffer = (const char *) buffer + add;
len -= add;
}
/* Process available complete blocks. */
if (len > 64)
{
transform( ctx, buffer, len & ~63);
buffer = (const char *) buffer + (len & ~63);
len &= 63;
}
/* Move remaining bytes in internal buffer. */
if (len > 0)
{
memcpy (ctx->buffer, buffer, len);
ctx->buflen = len;
}
}
/* 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 *ctx )
{
/* Take yet unprocessed bytes into account. */
u32 bytes = ctx->buflen;
size_t pad;
/* Now count remaining bytes. */
ctx->total[0] += bytes;
if( ctx->total[0] < bytes )
++ctx->total[1];
pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
memcpy (&ctx->buffer[bytes], fillbuf, pad);
/* Put the 64-bit file length in *bits* at the end of the buffer. */
*(u32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
*(u32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
(ctx->total[0] >> 29));
/* Process last bytes. */
transform( ctx, ctx->buffer, bytes + pad + 8);
/* Store the result in buffer */
((u32 *)ctx->buffer)[0] = SWAP (ctx->A);
((u32 *)ctx->buffer)[1] = SWAP (ctx->B);
((u32 *)ctx->buffer)[2] = SWAP (ctx->C);
((u32 *)ctx->buffer)[3] = SWAP (ctx->D);
}
static byte *
md5_read( MD5_CONTEXT *hd )
{
return hd->buffer;
}
/****************
* 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 *
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;
*r_init = (void (*)(void *))md5_init;
*r_write = (void (*)(void *, byte*, size_t))md5_write;
*r_final = (void (*)(void *))md5_final;
*r_read = (byte *(*)(void *))md5_read;
return "MD5";
}
/* end of file */
diff --git a/cipher/md5.h b/cipher/md5.h
index a4bcf5c63..89fc843cc 100644
--- a/cipher/md5.h
+++ b/cipher/md5.h
@@ -1,34 +1,34 @@
/* md5.h - message digest 5
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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_MD5_H
#define G10_MD5_H
const char *
md5_get_info( int algo, size_t *contextsize,
byte **r_asnoid, int *r_asn_len, 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 )
);
#endif /*G10_MD5_H*/
diff --git a/cipher/primegen.c b/cipher/primegen.c
index addc51fd5..e94842189 100644
--- a/cipher/primegen.c
+++ b/cipher/primegen.c
@@ -1,557 +1,557 @@
/* primegen.c - prime number generator
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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"
static int no_of_small_prime_numbers;
static MPI gen_prime( unsigned nbits, int mode, int randomlevel );
static int check_prime( MPI prime );
static int is_prime( MPI n, int steps, int *count );
static void m_out_of_n( char *array, int m, int n );
/****************
* Generate a prime number (stored in secure memory)
*/
MPI
generate_secret_prime( unsigned nbits )
{
MPI prime;
prime = gen_prime( nbits, 1, 2 );
fputc('\n', stderr);
return prime;
}
MPI
generate_public_prime( unsigned nbits )
{
MPI prime;
prime = gen_prime( nbits, 0, 2 );
fputc('\n', stderr);
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 */
/* 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, 1 );
q_factor = mode==1? gen_prime( req_qbits, 0, 1 ) : 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, 1 );
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, 1 );
factors[j++] = pool[i];
}
if( i == n ) {
m_free(perms); perms = NULL;
fputc('!', stderr);
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++;
fputc('>', stderr);
q = gen_prime( qbits, 0, 1 );
goto next_try;
}
}
else
count1 = 0;
if( nprime > pbits ) {
if( ++count2 > 20 ) {
count2 = 0;
qbits--;
fputc('<', stderr);
q = gen_prime( qbits, 0, 1 );
goto next_try;
}
}
else
count2 = 0;
} while( !(nprime == pbits && check_prime( prime )) );
if( DBG_CIPHER ) {
putc('\n', stderr);
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]) );
putc('\n', stderr);
}
if( ret_factors ) { /* caller wants the factors */
*ret_factors = m_alloc_clear( (n+2) * sizeof **ret_factors);
if( mode == 1 ) {
i = 0;
(*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
fputc('^', stderr);
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 )
fputc('\n', stderr);
} while( i < n+2 );
mpi_free(factors[n+1]);
mpi_free(tmp);
mpi_free(b);
mpi_free(pmin1);
}
if( !DBG_CIPHER )
putc('\n', stderr);
m_free( factors ); /* (factors are shallow copies) */
for(i=0; i < m; i++ )
mpi_free( pool[i] );
m_free( pool );
m_free(perms);
return prime;
}
static MPI
gen_prime( unsigned nbits, int secret, int randomlevel )
{
unsigned nlimbs;
MPI prime, val_2, val_3, result;
int i;
unsigned x, step;
unsigned 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( nlimbs );
mpi_set_ui(val_2, 2);
val_3 = mpi_alloc( nlimbs );
mpi_set_ui(val_3, 3);
result = mpi_alloc( nlimbs );
prime = secret? mpi_alloc_secure( nlimbs ): mpi_alloc( nlimbs );
count1 = count2 = 0;
/* enter (endless) loop */
for(;;) {
int dotcount=0;
/* generate a random number */
/*mpi_set_bytes( prime, nbits, get_random_byte, randomlevel );*/
{ 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 1 */
mpi_set_highbit( prime, nbits-1 );
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);
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 a already known prime */
mpi_add_ui( prime, prime, step );
#if 0
/* do a Fermat test */
count2++;
mpi_powm( result, val_2, prime, prime );
if( mpi_cmp_ui(result, 2) )
continue; /* stepping (fermat test failed) */
fputc('+', stderr);
#endif
/* perform stronger tests */
if( is_prime(prime, 5, &count2 ) ) {
if( !mpi_test_bit( prime, nbits-1 ) ) {
if( 0 && DBG_CIPHER ) {
fputc('\n', stderr);
log_debug("overflow in prime generation\n");
break; /* step loop, cont with a new prime */
}
}
if( 0 && DBG_CIPHER ) {
log_debug("performed %u simple and %u stronger tests\n",
count1, count2 );
log_mpidump("found prime: ", prime );
}
mpi_free(val_2);
mpi_free(val_3);
mpi_free(result);
m_free(mods);
return prime;
}
if( ++dotcount == 10 ) {
fputc('.', stderr);
dotcount = 0;
}
}
fputc(':', stderr); /* restart with a new random value */
}
}
/****************
* Returns: true if this may be a prime
*/
static int
check_prime( MPI prime )
{
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;
}
#if 0
result = mpi_alloc( mpi_get_nlimbs(prime) );
val_2 = mpi_alloc_set_ui( 2 );
mpi_powm( result, val_2, prime, prime );
if( mpi_cmp_ui(result, 2) ) {
mpi_free(result);
mpi_free(val_2);
return 0;
}
mpi_free(result);
mpi_free(val_2);
fputc('+', stderr);
#endif
/* perform stronger tests */
if( is_prime(prime, 5, &count ) )
return 1; /* is probably a prime */
fputc('.', stderr);
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 */
}
fputc('+', stderr);
}
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];
}
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index 514711700..2ca8dd854 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -1,547 +1,547 @@
/* pubkey.c - pubkey dispatcher
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "dynload.h"
#define TABLE_SIZE 10
struct pubkey_table_s {
const char *name;
int algo;
int npkey;
int nskey;
int nenc;
int nsig;
int usage;
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
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.
*/
static void
setup_pubkey_table()
{
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].usage );
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].usage );
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].usage );
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++;
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()
{
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 ) {
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->usage,
&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( !stricmp( 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;
}
int
check_pubkey_algo( int algo )
{
return check_pubkey_algo2( algo, 0 );
}
/****************
* a usage of 0 means: don't care
*/
int
check_pubkey_algo2( int algo, unsigned usage )
{
int i;
do {
for(i=0; pubkey_table[i].name; i++ )
if( pubkey_table[i].algo == algo ) {
if( (usage & PUBKEY_USAGE_SIG)
&& !(pubkey_table[i].usage & PUBKEY_USAGE_SIG) )
return G10ERR_WR_PUBKEY_ALGO;
if( (usage & PUBKEY_USAGE_ENC)
&& !(pubkey_table[i].usage & PUBKEY_USAGE_ENC) )
return G10ERR_WR_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() );
if( is_RSA(algo) ) /* special hack, so that we are able to */
return 2; /* see the RSA keyids */
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;
/* FIXME: check that data fits into the key (in xxx_encrypt)*/
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;
}
diff --git a/cipher/rand-internal.h b/cipher/rand-internal.h
index 230ea975e..290f034f9 100644
--- a/cipher/rand-internal.h
+++ b/cipher/rand-internal.h
@@ -1,30 +1,30 @@
/* rand-internal.h - header to glue the random functions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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);
#endif /*G10_RAND_INTERNAL_H*/
diff --git a/cipher/random.c b/cipher/random.c
index c49cc6e08..d57cd07ce 100644
--- a/cipher/random.c
+++ b/cipher/random.c
@@ -1,431 +1,431 @@
/* random.c - random number generator
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <sys/time.h>
#include <sys/types.h>
#include <sys/stat.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
#include "util.h"
#include "rmd.h"
#include "ttyio.h"
#include "i18n.h"
#include "random.h"
#include "rand-internal.h"
#include "dynload.h"
#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 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 void
initialize()
{
/* 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;
#if USE_RNDLINUX
rndlinux_constructor();
#elif USE_RNDUNIX
rndunix_constructor();
#elif USE_RNDW32
rndw32_constructor();
#elif USE_RNDOS2
rndos2_constructor();
#elif USE_RNDATARI
rndatari_constructor();
#elif USE_RNDMVS
rndmvs_constructor();
#endif
}
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, m_is_secure(buffer) );
memcpy( buffer, p, length );
m_free(p);
}
/****************
* 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;
size_t nbytes = (nbits+7)/8;
if( quick_test && level > 1 )
level = 1;
MASK_LEVEL(level);
buf = secure && secure_alloc ? m_alloc_secure( nbytes ) : m_alloc( nbytes );
read_pool( buf, nbytes, level );
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 );
}
}
static void
read_pool( byte *buffer, size_t length, int level )
{
int i;
ulong *sp, *dp;
if( length >= POOLSIZE )
BUG(); /* not allowed */
/* 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);
mix_pool(keypool);
memcpy( buffer, keypool, length );
}
else {
/* mix the pool (if add_randomness() didn't it) */
if( !just_mixed )
mix_pool(rndpool);
/* 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);
mix_pool(keypool);
/* 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.
*/
static void
add_randomness( const void *buffer, size_t length, int source )
{
if( !is_initialized )
initialize();
while( length-- ) {
rndpool[pool_writepos++] = *((byte*)buffer)++;
if( pool_writepos >= POOLSIZE ) {
if( source > 1 )
pool_filled = 1;
pool_writepos = 0;
mix_pool(rndpool);
just_mixed = !length;
}
}
}
static void
random_poll()
{
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;
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 HAVE_GETHRTIME
{ hrtime_t tv;
tv = gethrtime();
add_randomness( &tv, sizeof(tv), 1 );
}
#elif 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 );
}
#else /* use times */
{ struct tms buf;
times( &buf );
add_randomness( &buf, sizeof buf, 1 );
}
#endif
#ifdef HAVE_GETRUSAGE
{ struct rusage buf;
if( getrusage( RUSAGE_SELF, &buf ) )
BUG();
add_randomness( &buf, sizeof buf, 1 );
memset( &buf, 0, sizeof buf );
}
#endif
}
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;
int nbytes;
int goodness;
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 */
}
diff --git a/cipher/random.h b/cipher/random.h
index d4c134275..ca9ee3ab7 100644
--- a/cipher/random.h
+++ b/cipher/random.h
@@ -1,32 +1,32 @@
/* random.h - random functions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 secure_random_alloc(void);
int quick_random_gen( int onoff );
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 );
#endif /*G10_RANDOM_H*/
diff --git a/cipher/rmd.h b/cipher/rmd.h
index 64a8a02b5..0c1fbad99 100644
--- a/cipher/rmd.h
+++ b/cipher/rmd.h
@@ -1,47 +1,47 @@
/* rmd.h - RIPE-MD hash functions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 );
const char *
rmd160_get_info( int algo, size_t *contextsize,
byte **r_asnoid, int *r_asn_len, 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 )
);
#endif /*G10_RMD_H*/
diff --git a/cipher/rmd160.c b/cipher/rmd160.c
index 3b1702cb0..4d644756f 100644
--- a/cipher/rmd160.c
+++ b/cipher/rmd160.c
@@ -1,584 +1,584 @@
/* rmd160.c - RIPE-MD160
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 */
/*********************************
* 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
*/
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;
}
#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
/****************
* 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(s,t) + e; \
c = rol(10,c); \
} 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 );
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;
}
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 */;
msb = 0;
t = hd->nblocks;
if( (lsb = t << 6) < t ) /* multiply by 64 to make a byte count */
msb++;
msb += t >> 26;
t = lsb;
if( (lsb = t + hd->count) < t ) /* add the count */
msb++;
t = lsb;
if( (lsb = t << 3) < t ) /* multiply by 8 to make a bit count */
msb++;
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 );
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.
*/
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;
*r_init = (void (*)(void *))rmd160_init;
*r_write = (void (*)(void *, byte*, size_t))rmd160_write;
*r_final = (void (*)(void *))rmd160_final;
*r_read = (byte *(*)(void *))rmd160_read;
return "RIPEMD160";
}
diff --git a/cipher/rmd160test.c b/cipher/rmd160test.c
index bfbd9bc83..f0acd2ad6 100644
--- a/cipher/rmd160test.c
+++ b/cipher/rmd160test.c
@@ -1,63 +1,63 @@
/* rmd160test.c - ripe md 160 test program
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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;
}
diff --git a/cipher/sha1.c b/cipher/sha1.c
index 0a6ffab2c..b3da296f8 100644
--- a/cipher/sha1.c
+++ b/cipher/sha1.c
@@ -1,360 +1,360 @@
/* sha1.c - SHA1 hash function
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* Please see below for more legal information!
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "sha1.h"
typedef struct {
u32 h0,h1,h2,h3,h4;
u32 nblocks;
byte buf[64];
int count;
} SHA1_CONTEXT;
#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
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] = (tm << 1) | (tm >> 31)) )
#define R(a,b,c,d,e,f,k,m) do { e += rol( 5, a ) \
+ f( b, c, d ) \
+ k \
+ m; \
b = rol( 30, b ); \
} 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 );
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;
}
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 */;
msb = 0;
t = hd->nblocks;
if( (lsb = t << 6) < t ) /* multiply by 64 to make a byte count */
msb++;
msb += t >> 26;
t = lsb;
if( (lsb = t + hd->count) < t ) /* add the count */
msb++;
t = lsb;
if( (lsb = t << 3) < t ) /* multiply by 8 to make a bit count */
msb++;
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 );
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.
*/
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;
*r_init = (void (*)(void *))sha1_init;
*r_write = (void (*)(void *, byte*, size_t))sha1_write;
*r_final = (void (*)(void *))sha1_final;
*r_read = (byte *(*)(void *))sha1_read;
return "SHA1";
}
diff --git a/cipher/sha1.h b/cipher/sha1.h
index 2a47b3e91..3d9302671 100644
--- a/cipher/sha1.h
+++ b/cipher/sha1.h
@@ -1,33 +1,33 @@
/* sha1.h - SHA1 hash function
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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_SHA1_H
#define G10_SHA1_H
const char *
sha1_get_info( int algo, size_t *contextsize,
byte **r_asnoid, int *r_asn_len, 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 )
);
#endif /*G10_SHA1_H*/
diff --git a/cipher/smallprime.c b/cipher/smallprime.c
index a286aa658..8187aa768 100644
--- a/cipher/smallprime.c
+++ b/cipher/smallprime.c
@@ -1,114 +1,114 @@
/* smallprime.c - List of small primes
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
};
diff --git a/cipher/tiger.c b/cipher/tiger.c
index c473e92d3..51c6450c8 100644
--- a/cipher/tiger.c
+++ b/cipher/tiger.c
@@ -1,967 +1,967 @@
/* tiger.c - The TIGER hash function
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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"
typedef struct {
u64 a, b, c;
byte buf[64];
int count;
u32 nblocks;
} TIGER_CONTEXT;
/*********************************
* Okay, okay, this is not the fastest code - improvements are welcome.
*
*/
/* Some test vectors:
* "" 24F0130C63AC9332 16166E76B1BB925F F373DE2D49584E7A
* "abc" F258C1E88414AB2A 527AB541FFC5B8BF 935F7B951C132951
* "Tiger" 9F00F599072300DD 276ABB38C8EB6DEC 37790C116F9D2BDF
* "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"
* 87FB2A9083851CF7 470D2CF810E6DF9E B586445034A5A386
* "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789"
* 467DB80863EBCE48 8DF1CD1261655DE9 57896565975F9197
* "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham"
* 0C410A042968868A 1671DA5A3FD29A72 5EC1E457D3CDB303
* "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proc"
* "eedings of Fast Software Encryption 3, Cambridge."
* EBF591D5AFA655CE 7F22894FF87F54AC 89C811B6B0DA3193
* "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proc"
* "eedings of Fast Software Encryption 3, Cambridge, 1996."
* 3D9AEB03D1BD1A63 57B2774DFD6D5B24 DD68151D503974FC
* "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEF"
* "GHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"
* 00B83EB4E53440C5 76AC6AAEE0A74858 25FD15E70A59FFE4
*/
static u64 sbox1[256] = {
0x02aab17cf7e90c5eLL /* 0 */, 0xac424b03e243a8ecLL /* 1 */,
0x72cd5be30dd5fcd3LL /* 2 */, 0x6d019b93f6f97f3aLL /* 3 */,
0xcd9978ffd21f9193LL /* 4 */, 0x7573a1c9708029e2LL /* 5 */,
0xb164326b922a83c3LL /* 6 */, 0x46883eee04915870LL /* 7 */,
0xeaace3057103ece6LL /* 8 */, 0xc54169b808a3535cLL /* 9 */,
0x4ce754918ddec47cLL /* 10 */, 0x0aa2f4dfdc0df40cLL /* 11 */,
0x10b76f18a74dbefaLL /* 12 */, 0xc6ccb6235ad1ab6aLL /* 13 */,
0x13726121572fe2ffLL /* 14 */, 0x1a488c6f199d921eLL /* 15 */,
0x4bc9f9f4da0007caLL /* 16 */, 0x26f5e6f6e85241c7LL /* 17 */,
0x859079dbea5947b6LL /* 18 */, 0x4f1885c5c99e8c92LL /* 19 */,
0xd78e761ea96f864bLL /* 20 */, 0x8e36428c52b5c17dLL /* 21 */,
0x69cf6827373063c1LL /* 22 */, 0xb607c93d9bb4c56eLL /* 23 */,
0x7d820e760e76b5eaLL /* 24 */, 0x645c9cc6f07fdc42LL /* 25 */,
0xbf38a078243342e0LL /* 26 */, 0x5f6b343c9d2e7d04LL /* 27 */,
0xf2c28aeb600b0ec6LL /* 28 */, 0x6c0ed85f7254bcacLL /* 29 */,
0x71592281a4db4fe5LL /* 30 */, 0x1967fa69ce0fed9fLL /* 31 */,
0xfd5293f8b96545dbLL /* 32 */, 0xc879e9d7f2a7600bLL /* 33 */,
0x860248920193194eLL /* 34 */, 0xa4f9533b2d9cc0b3LL /* 35 */,
0x9053836c15957613LL /* 36 */, 0xdb6dcf8afc357bf1LL /* 37 */,
0x18beea7a7a370f57LL /* 38 */, 0x037117ca50b99066LL /* 39 */,
0x6ab30a9774424a35LL /* 40 */, 0xf4e92f02e325249bLL /* 41 */,
0x7739db07061ccae1LL /* 42 */, 0xd8f3b49ceca42a05LL /* 43 */,
0xbd56be3f51382f73LL /* 44 */, 0x45faed5843b0bb28LL /* 45 */,
0x1c813d5c11bf1f83LL /* 46 */, 0x8af0e4b6d75fa169LL /* 47 */,
0x33ee18a487ad9999LL /* 48 */, 0x3c26e8eab1c94410LL /* 49 */,
0xb510102bc0a822f9LL /* 50 */, 0x141eef310ce6123bLL /* 51 */,
0xfc65b90059ddb154LL /* 52 */, 0xe0158640c5e0e607LL /* 53 */,
0x884e079826c3a3cfLL /* 54 */, 0x930d0d9523c535fdLL /* 55 */,
0x35638d754e9a2b00LL /* 56 */, 0x4085fccf40469dd5LL /* 57 */,
0xc4b17ad28be23a4cLL /* 58 */, 0xcab2f0fc6a3e6a2eLL /* 59 */,
0x2860971a6b943fcdLL /* 60 */, 0x3dde6ee212e30446LL /* 61 */,
0x6222f32ae01765aeLL /* 62 */, 0x5d550bb5478308feLL /* 63 */,
0xa9efa98da0eda22aLL /* 64 */, 0xc351a71686c40da7LL /* 65 */,
0x1105586d9c867c84LL /* 66 */, 0xdcffee85fda22853LL /* 67 */,
0xccfbd0262c5eef76LL /* 68 */, 0xbaf294cb8990d201LL /* 69 */,
0xe69464f52afad975LL /* 70 */, 0x94b013afdf133e14LL /* 71 */,
0x06a7d1a32823c958LL /* 72 */, 0x6f95fe5130f61119LL /* 73 */,
0xd92ab34e462c06c0LL /* 74 */, 0xed7bde33887c71d2LL /* 75 */,
0x79746d6e6518393eLL /* 76 */, 0x5ba419385d713329LL /* 77 */,
0x7c1ba6b948a97564LL /* 78 */, 0x31987c197bfdac67LL /* 79 */,
0xde6c23c44b053d02LL /* 80 */, 0x581c49fed002d64dLL /* 81 */,
0xdd474d6338261571LL /* 82 */, 0xaa4546c3e473d062LL /* 83 */,
0x928fce349455f860LL /* 84 */, 0x48161bbacaab94d9LL /* 85 */,
0x63912430770e6f68LL /* 86 */, 0x6ec8a5e602c6641cLL /* 87 */,
0x87282515337ddd2bLL /* 88 */, 0x2cda6b42034b701bLL /* 89 */,
0xb03d37c181cb096dLL /* 90 */, 0xe108438266c71c6fLL /* 91 */,
0x2b3180c7eb51b255LL /* 92 */, 0xdf92b82f96c08bbcLL /* 93 */,
0x5c68c8c0a632f3baLL /* 94 */, 0x5504cc861c3d0556LL /* 95 */,
0xabbfa4e55fb26b8fLL /* 96 */, 0x41848b0ab3baceb4LL /* 97 */,
0xb334a273aa445d32LL /* 98 */, 0xbca696f0a85ad881LL /* 99 */,
0x24f6ec65b528d56cLL /* 100 */, 0x0ce1512e90f4524aLL /* 101 */,
0x4e9dd79d5506d35aLL /* 102 */, 0x258905fac6ce9779LL /* 103 */,
0x2019295b3e109b33LL /* 104 */, 0xf8a9478b73a054ccLL /* 105 */,
0x2924f2f934417eb0LL /* 106 */, 0x3993357d536d1bc4LL /* 107 */,
0x38a81ac21db6ff8bLL /* 108 */, 0x47c4fbf17d6016bfLL /* 109 */,
0x1e0faadd7667e3f5LL /* 110 */, 0x7abcff62938beb96LL /* 111 */,
0xa78dad948fc179c9LL /* 112 */, 0x8f1f98b72911e50dLL /* 113 */,
0x61e48eae27121a91LL /* 114 */, 0x4d62f7ad31859808LL /* 115 */,
0xeceba345ef5ceaebLL /* 116 */, 0xf5ceb25ebc9684ceLL /* 117 */,
0xf633e20cb7f76221LL /* 118 */, 0xa32cdf06ab8293e4LL /* 119 */,
0x985a202ca5ee2ca4LL /* 120 */, 0xcf0b8447cc8a8fb1LL /* 121 */,
0x9f765244979859a3LL /* 122 */, 0xa8d516b1a1240017LL /* 123 */,
0x0bd7ba3ebb5dc726LL /* 124 */, 0xe54bca55b86adb39LL /* 125 */,
0x1d7a3afd6c478063LL /* 126 */, 0x519ec608e7669eddLL /* 127 */,
0x0e5715a2d149aa23LL /* 128 */, 0x177d4571848ff194LL /* 129 */,
0xeeb55f3241014c22LL /* 130 */, 0x0f5e5ca13a6e2ec2LL /* 131 */,
0x8029927b75f5c361LL /* 132 */, 0xad139fabc3d6e436LL /* 133 */,
0x0d5df1a94ccf402fLL /* 134 */, 0x3e8bd948bea5dfc8LL /* 135 */,
0xa5a0d357bd3ff77eLL /* 136 */, 0xa2d12e251f74f645LL /* 137 */,
0x66fd9e525e81a082LL /* 138 */, 0x2e0c90ce7f687a49LL /* 139 */,
0xc2e8bcbeba973bc5LL /* 140 */, 0x000001bce509745fLL /* 141 */,
0x423777bbe6dab3d6LL /* 142 */, 0xd1661c7eaef06eb5LL /* 143 */,
0xa1781f354daacfd8LL /* 144 */, 0x2d11284a2b16affcLL /* 145 */,
0xf1fc4f67fa891d1fLL /* 146 */, 0x73ecc25dcb920adaLL /* 147 */,
0xae610c22c2a12651LL /* 148 */, 0x96e0a810d356b78aLL /* 149 */,
0x5a9a381f2fe7870fLL /* 150 */, 0xd5ad62ede94e5530LL /* 151 */,
0xd225e5e8368d1427LL /* 152 */, 0x65977b70c7af4631LL /* 153 */,
0x99f889b2de39d74fLL /* 154 */, 0x233f30bf54e1d143LL /* 155 */,
0x9a9675d3d9a63c97LL /* 156 */, 0x5470554ff334f9a8LL /* 157 */,
0x166acb744a4f5688LL /* 158 */, 0x70c74caab2e4aeadLL /* 159 */,
0xf0d091646f294d12LL /* 160 */, 0x57b82a89684031d1LL /* 161 */,
0xefd95a5a61be0b6bLL /* 162 */, 0x2fbd12e969f2f29aLL /* 163 */,
0x9bd37013feff9fe8LL /* 164 */, 0x3f9b0404d6085a06LL /* 165 */,
0x4940c1f3166cfe15LL /* 166 */, 0x09542c4dcdf3defbLL /* 167 */,
0xb4c5218385cd5ce3LL /* 168 */, 0xc935b7dc4462a641LL /* 169 */,
0x3417f8a68ed3b63fLL /* 170 */, 0xb80959295b215b40LL /* 171 */,
0xf99cdaef3b8c8572LL /* 172 */, 0x018c0614f8fcb95dLL /* 173 */,
0x1b14accd1a3acdf3LL /* 174 */, 0x84d471f200bb732dLL /* 175 */,
0xc1a3110e95e8da16LL /* 176 */, 0x430a7220bf1a82b8LL /* 177 */,
0xb77e090d39df210eLL /* 178 */, 0x5ef4bd9f3cd05e9dLL /* 179 */,
0x9d4ff6da7e57a444LL /* 180 */, 0xda1d60e183d4a5f8LL /* 181 */,
0xb287c38417998e47LL /* 182 */, 0xfe3edc121bb31886LL /* 183 */,
0xc7fe3ccc980ccbefLL /* 184 */, 0xe46fb590189bfd03LL /* 185 */,
0x3732fd469a4c57dcLL /* 186 */, 0x7ef700a07cf1ad65LL /* 187 */,
0x59c64468a31d8859LL /* 188 */, 0x762fb0b4d45b61f6LL /* 189 */,
0x155baed099047718LL /* 190 */, 0x68755e4c3d50baa6LL /* 191 */,
0xe9214e7f22d8b4dfLL /* 192 */, 0x2addbf532eac95f4LL /* 193 */,
0x32ae3909b4bd0109LL /* 194 */, 0x834df537b08e3450LL /* 195 */,
0xfa209da84220728dLL /* 196 */, 0x9e691d9b9efe23f7LL /* 197 */,
0x0446d288c4ae8d7fLL /* 198 */, 0x7b4cc524e169785bLL /* 199 */,
0x21d87f0135ca1385LL /* 200 */, 0xcebb400f137b8aa5LL /* 201 */,
0x272e2b66580796beLL /* 202 */, 0x3612264125c2b0deLL /* 203 */,
0x057702bdad1efbb2LL /* 204 */, 0xd4babb8eacf84be9LL /* 205 */,
0x91583139641bc67bLL /* 206 */, 0x8bdc2de08036e024LL /* 207 */,
0x603c8156f49f68edLL /* 208 */, 0xf7d236f7dbef5111LL /* 209 */,
0x9727c4598ad21e80LL /* 210 */, 0xa08a0896670a5fd7LL /* 211 */,
0xcb4a8f4309eba9cbLL /* 212 */, 0x81af564b0f7036a1LL /* 213 */,
0xc0b99aa778199abdLL /* 214 */, 0x959f1ec83fc8e952LL /* 215 */,
0x8c505077794a81b9LL /* 216 */, 0x3acaaf8f056338f0LL /* 217 */,
0x07b43f50627a6778LL /* 218 */, 0x4a44ab49f5eccc77LL /* 219 */,
0x3bc3d6e4b679ee98LL /* 220 */, 0x9cc0d4d1cf14108cLL /* 221 */,
0x4406c00b206bc8a0LL /* 222 */, 0x82a18854c8d72d89LL /* 223 */,
0x67e366b35c3c432cLL /* 224 */, 0xb923dd61102b37f2LL /* 225 */,
0x56ab2779d884271dLL /* 226 */, 0xbe83e1b0ff1525afLL /* 227 */,
0xfb7c65d4217e49a9LL /* 228 */, 0x6bdbe0e76d48e7d4LL /* 229 */,
0x08df828745d9179eLL /* 230 */, 0x22ea6a9add53bd34LL /* 231 */,
0xe36e141c5622200aLL /* 232 */, 0x7f805d1b8cb750eeLL /* 233 */,
0xafe5c7a59f58e837LL /* 234 */, 0xe27f996a4fb1c23cLL /* 235 */,
0xd3867dfb0775f0d0LL /* 236 */, 0xd0e673de6e88891aLL /* 237 */,
0x123aeb9eafb86c25LL /* 238 */, 0x30f1d5d5c145b895LL /* 239 */,
0xbb434a2dee7269e7LL /* 240 */, 0x78cb67ecf931fa38LL /* 241 */,
0xf33b0372323bbf9cLL /* 242 */, 0x52d66336fb279c74LL /* 243 */,
0x505f33ac0afb4eaaLL /* 244 */, 0xe8a5cd99a2cce187LL /* 245 */,
0x534974801e2d30bbLL /* 246 */, 0x8d2d5711d5876d90LL /* 247 */,
0x1f1a412891bc038eLL /* 248 */, 0xd6e2e71d82e56648LL /* 249 */,
0x74036c3a497732b7LL /* 250 */, 0x89b67ed96361f5abLL /* 251 */,
0xffed95d8f1ea02a2LL /* 252 */, 0xe72b3bd61464d43dLL /* 253 */,
0xa6300f170bdc4820LL /* 254 */, 0xebc18760ed78a77aLL /* 255 */
};
static u64 sbox2[256] = {
0xe6a6be5a05a12138LL /* 256 */, 0xb5a122a5b4f87c98LL /* 257 */,
0x563c6089140b6990LL /* 258 */, 0x4c46cb2e391f5dd5LL /* 259 */,
0xd932addbc9b79434LL /* 260 */, 0x08ea70e42015aff5LL /* 261 */,
0xd765a6673e478cf1LL /* 262 */, 0xc4fb757eab278d99LL /* 263 */,
0xdf11c6862d6e0692LL /* 264 */, 0xddeb84f10d7f3b16LL /* 265 */,
0x6f2ef604a665ea04LL /* 266 */, 0x4a8e0f0ff0e0dfb3LL /* 267 */,
0xa5edeef83dbcba51LL /* 268 */, 0xfc4f0a2a0ea4371eLL /* 269 */,
0xe83e1da85cb38429LL /* 270 */, 0xdc8ff882ba1b1ce2LL /* 271 */,
0xcd45505e8353e80dLL /* 272 */, 0x18d19a00d4db0717LL /* 273 */,
0x34a0cfeda5f38101LL /* 274 */, 0x0be77e518887caf2LL /* 275 */,
0x1e341438b3c45136LL /* 276 */, 0xe05797f49089ccf9LL /* 277 */,
0xffd23f9df2591d14LL /* 278 */, 0x543dda228595c5cdLL /* 279 */,
0x661f81fd99052a33LL /* 280 */, 0x8736e641db0f7b76LL /* 281 */,
0x15227725418e5307LL /* 282 */, 0xe25f7f46162eb2faLL /* 283 */,
0x48a8b2126c13d9feLL /* 284 */, 0xafdc541792e76eeaLL /* 285 */,
0x03d912bfc6d1898fLL /* 286 */, 0x31b1aafa1b83f51bLL /* 287 */,
0xf1ac2796e42ab7d9LL /* 288 */, 0x40a3a7d7fcd2ebacLL /* 289 */,
0x1056136d0afbbcc5LL /* 290 */, 0x7889e1dd9a6d0c85LL /* 291 */,
0xd33525782a7974aaLL /* 292 */, 0xa7e25d09078ac09bLL /* 293 */,
0xbd4138b3eac6edd0LL /* 294 */, 0x920abfbe71eb9e70LL /* 295 */,
0xa2a5d0f54fc2625cLL /* 296 */, 0xc054e36b0b1290a3LL /* 297 */,
0xf6dd59ff62fe932bLL /* 298 */, 0x3537354511a8ac7dLL /* 299 */,
0xca845e9172fadcd4LL /* 300 */, 0x84f82b60329d20dcLL /* 301 */,
0x79c62ce1cd672f18LL /* 302 */, 0x8b09a2add124642cLL /* 303 */,
0xd0c1e96a19d9e726LL /* 304 */, 0x5a786a9b4ba9500cLL /* 305 */,
0x0e020336634c43f3LL /* 306 */, 0xc17b474aeb66d822LL /* 307 */,
0x6a731ae3ec9baac2LL /* 308 */, 0x8226667ae0840258LL /* 309 */,
0x67d4567691caeca5LL /* 310 */, 0x1d94155c4875adb5LL /* 311 */,
0x6d00fd985b813fdfLL /* 312 */, 0x51286efcb774cd06LL /* 313 */,
0x5e8834471fa744afLL /* 314 */, 0xf72ca0aee761ae2eLL /* 315 */,
0xbe40e4cdaee8e09aLL /* 316 */, 0xe9970bbb5118f665LL /* 317 */,
0x726e4beb33df1964LL /* 318 */, 0x703b000729199762LL /* 319 */,
0x4631d816f5ef30a7LL /* 320 */, 0xb880b5b51504a6beLL /* 321 */,
0x641793c37ed84b6cLL /* 322 */, 0x7b21ed77f6e97d96LL /* 323 */,
0x776306312ef96b73LL /* 324 */, 0xae528948e86ff3f4LL /* 325 */,
0x53dbd7f286a3f8f8LL /* 326 */, 0x16cadce74cfc1063LL /* 327 */,
0x005c19bdfa52c6ddLL /* 328 */, 0x68868f5d64d46ad3LL /* 329 */,
0x3a9d512ccf1e186aLL /* 330 */, 0x367e62c2385660aeLL /* 331 */,
0xe359e7ea77dcb1d7LL /* 332 */, 0x526c0773749abe6eLL /* 333 */,
0x735ae5f9d09f734bLL /* 334 */, 0x493fc7cc8a558ba8LL /* 335 */,
0xb0b9c1533041ab45LL /* 336 */, 0x321958ba470a59bdLL /* 337 */,
0x852db00b5f46c393LL /* 338 */, 0x91209b2bd336b0e5LL /* 339 */,
0x6e604f7d659ef19fLL /* 340 */, 0xb99a8ae2782ccb24LL /* 341 */,
0xccf52ab6c814c4c7LL /* 342 */, 0x4727d9afbe11727bLL /* 343 */,
0x7e950d0c0121b34dLL /* 344 */, 0x756f435670ad471fLL /* 345 */,
0xf5add442615a6849LL /* 346 */, 0x4e87e09980b9957aLL /* 347 */,
0x2acfa1df50aee355LL /* 348 */, 0xd898263afd2fd556LL /* 349 */,
0xc8f4924dd80c8fd6LL /* 350 */, 0xcf99ca3d754a173aLL /* 351 */,
0xfe477bacaf91bf3cLL /* 352 */, 0xed5371f6d690c12dLL /* 353 */,
0x831a5c285e687094LL /* 354 */, 0xc5d3c90a3708a0a4LL /* 355 */,
0x0f7f903717d06580LL /* 356 */, 0x19f9bb13b8fdf27fLL /* 357 */,
0xb1bd6f1b4d502843LL /* 358 */, 0x1c761ba38fff4012LL /* 359 */,
0x0d1530c4e2e21f3bLL /* 360 */, 0x8943ce69a7372c8aLL /* 361 */,
0xe5184e11feb5ce66LL /* 362 */, 0x618bdb80bd736621LL /* 363 */,
0x7d29bad68b574d0bLL /* 364 */, 0x81bb613e25e6fe5bLL /* 365 */,
0x071c9c10bc07913fLL /* 366 */, 0xc7beeb7909ac2d97LL /* 367 */,
0xc3e58d353bc5d757LL /* 368 */, 0xeb017892f38f61e8LL /* 369 */,
0xd4effb9c9b1cc21aLL /* 370 */, 0x99727d26f494f7abLL /* 371 */,
0xa3e063a2956b3e03LL /* 372 */, 0x9d4a8b9a4aa09c30LL /* 373 */,
0x3f6ab7d500090fb4LL /* 374 */, 0x9cc0f2a057268ac0LL /* 375 */,
0x3dee9d2dedbf42d1LL /* 376 */, 0x330f49c87960a972LL /* 377 */,
0xc6b2720287421b41LL /* 378 */, 0x0ac59ec07c00369cLL /* 379 */,
0xef4eac49cb353425LL /* 380 */, 0xf450244eef0129d8LL /* 381 */,
0x8acc46e5caf4deb6LL /* 382 */, 0x2ffeab63989263f7LL /* 383 */,
0x8f7cb9fe5d7a4578LL /* 384 */, 0x5bd8f7644e634635LL /* 385 */,
0x427a7315bf2dc900LL /* 386 */, 0x17d0c4aa2125261cLL /* 387 */,
0x3992486c93518e50LL /* 388 */, 0xb4cbfee0a2d7d4c3LL /* 389 */,
0x7c75d6202c5ddd8dLL /* 390 */, 0xdbc295d8e35b6c61LL /* 391 */,
0x60b369d302032b19LL /* 392 */, 0xce42685fdce44132LL /* 393 */,
0x06f3ddb9ddf65610LL /* 394 */, 0x8ea4d21db5e148f0LL /* 395 */,
0x20b0fce62fcd496fLL /* 396 */, 0x2c1b912358b0ee31LL /* 397 */,
0xb28317b818f5a308LL /* 398 */, 0xa89c1e189ca6d2cfLL /* 399 */,
0x0c6b18576aaadbc8LL /* 400 */, 0xb65deaa91299fae3LL /* 401 */,
0xfb2b794b7f1027e7LL /* 402 */, 0x04e4317f443b5bebLL /* 403 */,
0x4b852d325939d0a6LL /* 404 */, 0xd5ae6beefb207ffcLL /* 405 */,
0x309682b281c7d374LL /* 406 */, 0xbae309a194c3b475LL /* 407 */,
0x8cc3f97b13b49f05LL /* 408 */, 0x98a9422ff8293967LL /* 409 */,
0x244b16b01076ff7cLL /* 410 */, 0xf8bf571c663d67eeLL /* 411 */,
0x1f0d6758eee30da1LL /* 412 */, 0xc9b611d97adeb9b7LL /* 413 */,
0xb7afd5887b6c57a2LL /* 414 */, 0x6290ae846b984fe1LL /* 415 */,
0x94df4cdeacc1a5fdLL /* 416 */, 0x058a5bd1c5483affLL /* 417 */,
0x63166cc142ba3c37LL /* 418 */, 0x8db8526eb2f76f40LL /* 419 */,
0xe10880036f0d6d4eLL /* 420 */, 0x9e0523c9971d311dLL /* 421 */,
0x45ec2824cc7cd691LL /* 422 */, 0x575b8359e62382c9LL /* 423 */,
0xfa9e400dc4889995LL /* 424 */, 0xd1823ecb45721568LL /* 425 */,
0xdafd983b8206082fLL /* 426 */, 0xaa7d29082386a8cbLL /* 427 */,
0x269fcd4403b87588LL /* 428 */, 0x1b91f5f728bdd1e0LL /* 429 */,
0xe4669f39040201f6LL /* 430 */, 0x7a1d7c218cf04adeLL /* 431 */,
0x65623c29d79ce5ceLL /* 432 */, 0x2368449096c00bb1LL /* 433 */,
0xab9bf1879da503baLL /* 434 */, 0xbc23ecb1a458058eLL /* 435 */,
0x9a58df01bb401eccLL /* 436 */, 0xa070e868a85f143dLL /* 437 */,
0x4ff188307df2239eLL /* 438 */, 0x14d565b41a641183LL /* 439 */,
0xee13337452701602LL /* 440 */, 0x950e3dcf3f285e09LL /* 441 */,
0x59930254b9c80953LL /* 442 */, 0x3bf299408930da6dLL /* 443 */,
0xa955943f53691387LL /* 444 */, 0xa15edecaa9cb8784LL /* 445 */,
0x29142127352be9a0LL /* 446 */, 0x76f0371fff4e7afbLL /* 447 */,
0x0239f450274f2228LL /* 448 */, 0xbb073af01d5e868bLL /* 449 */,
0xbfc80571c10e96c1LL /* 450 */, 0xd267088568222e23LL /* 451 */,
0x9671a3d48e80b5b0LL /* 452 */, 0x55b5d38ae193bb81LL /* 453 */,
0x693ae2d0a18b04b8LL /* 454 */, 0x5c48b4ecadd5335fLL /* 455 */,
0xfd743b194916a1caLL /* 456 */, 0x2577018134be98c4LL /* 457 */,
0xe77987e83c54a4adLL /* 458 */, 0x28e11014da33e1b9LL /* 459 */,
0x270cc59e226aa213LL /* 460 */, 0x71495f756d1a5f60LL /* 461 */,
0x9be853fb60afef77LL /* 462 */, 0xadc786a7f7443dbfLL /* 463 */,
0x0904456173b29a82LL /* 464 */, 0x58bc7a66c232bd5eLL /* 465 */,
0xf306558c673ac8b2LL /* 466 */, 0x41f639c6b6c9772aLL /* 467 */,
0x216defe99fda35daLL /* 468 */, 0x11640cc71c7be615LL /* 469 */,
0x93c43694565c5527LL /* 470 */, 0xea038e6246777839LL /* 471 */,
0xf9abf3ce5a3e2469LL /* 472 */, 0x741e768d0fd312d2LL /* 473 */,
0x0144b883ced652c6LL /* 474 */, 0xc20b5a5ba33f8552LL /* 475 */,
0x1ae69633c3435a9dLL /* 476 */, 0x97a28ca4088cfdecLL /* 477 */,
0x8824a43c1e96f420LL /* 478 */, 0x37612fa66eeea746LL /* 479 */,
0x6b4cb165f9cf0e5aLL /* 480 */, 0x43aa1c06a0abfb4aLL /* 481 */,
0x7f4dc26ff162796bLL /* 482 */, 0x6cbacc8e54ed9b0fLL /* 483 */,
0xa6b7ffefd2bb253eLL /* 484 */, 0x2e25bc95b0a29d4fLL /* 485 */,
0x86d6a58bdef1388cLL /* 486 */, 0xded74ac576b6f054LL /* 487 */,
0x8030bdbc2b45805dLL /* 488 */, 0x3c81af70e94d9289LL /* 489 */,
0x3eff6dda9e3100dbLL /* 490 */, 0xb38dc39fdfcc8847LL /* 491 */,
0x123885528d17b87eLL /* 492 */, 0xf2da0ed240b1b642LL /* 493 */,
0x44cefadcd54bf9a9LL /* 494 */, 0x1312200e433c7ee6LL /* 495 */,
0x9ffcc84f3a78c748LL /* 496 */, 0xf0cd1f72248576bbLL /* 497 */,
0xec6974053638cfe4LL /* 498 */, 0x2ba7b67c0cec4e4cLL /* 499 */,
0xac2f4df3e5ce32edLL /* 500 */, 0xcb33d14326ea4c11LL /* 501 */,
0xa4e9044cc77e58bcLL /* 502 */, 0x5f513293d934fcefLL /* 503 */,
0x5dc9645506e55444LL /* 504 */, 0x50de418f317de40aLL /* 505 */,
0x388cb31a69dde259LL /* 506 */, 0x2db4a83455820a86LL /* 507 */,
0x9010a91e84711ae9LL /* 508 */, 0x4df7f0b7b1498371LL /* 509 */,
0xd62a2eabc0977179LL /* 510 */, 0x22fac097aa8d5c0eLL /* 511 */
};
static u64 sbox3[256] = {
0xf49fcc2ff1daf39bLL /* 512 */, 0x487fd5c66ff29281LL /* 513 */,
0xe8a30667fcdca83fLL /* 514 */, 0x2c9b4be3d2fcce63LL /* 515 */,
0xda3ff74b93fbbbc2LL /* 516 */, 0x2fa165d2fe70ba66LL /* 517 */,
0xa103e279970e93d4LL /* 518 */, 0xbecdec77b0e45e71LL /* 519 */,
0xcfb41e723985e497LL /* 520 */, 0xb70aaa025ef75017LL /* 521 */,
0xd42309f03840b8e0LL /* 522 */, 0x8efc1ad035898579LL /* 523 */,
0x96c6920be2b2abc5LL /* 524 */, 0x66af4163375a9172LL /* 525 */,
0x2174abdcca7127fbLL /* 526 */, 0xb33ccea64a72ff41LL /* 527 */,
0xf04a4933083066a5LL /* 528 */, 0x8d970acdd7289af5LL /* 529 */,
0x8f96e8e031c8c25eLL /* 530 */, 0xf3fec02276875d47LL /* 531 */,
0xec7bf310056190ddLL /* 532 */, 0xf5adb0aebb0f1491LL /* 533 */,
0x9b50f8850fd58892LL /* 534 */, 0x4975488358b74de8LL /* 535 */,
0xa3354ff691531c61LL /* 536 */, 0x0702bbe481d2c6eeLL /* 537 */,
0x89fb24057deded98LL /* 538 */, 0xac3075138596e902LL /* 539 */,
0x1d2d3580172772edLL /* 540 */, 0xeb738fc28e6bc30dLL /* 541 */,
0x5854ef8f63044326LL /* 542 */, 0x9e5c52325add3bbeLL /* 543 */,
0x90aa53cf325c4623LL /* 544 */, 0xc1d24d51349dd067LL /* 545 */,
0x2051cfeea69ea624LL /* 546 */, 0x13220f0a862e7e4fLL /* 547 */,
0xce39399404e04864LL /* 548 */, 0xd9c42ca47086fcb7LL /* 549 */,
0x685ad2238a03e7ccLL /* 550 */, 0x066484b2ab2ff1dbLL /* 551 */,
0xfe9d5d70efbf79ecLL /* 552 */, 0x5b13b9dd9c481854LL /* 553 */,
0x15f0d475ed1509adLL /* 554 */, 0x0bebcd060ec79851LL /* 555 */,
0xd58c6791183ab7f8LL /* 556 */, 0xd1187c5052f3eee4LL /* 557 */,
0xc95d1192e54e82ffLL /* 558 */, 0x86eea14cb9ac6ca2LL /* 559 */,
0x3485beb153677d5dLL /* 560 */, 0xdd191d781f8c492aLL /* 561 */,
0xf60866baa784ebf9LL /* 562 */, 0x518f643ba2d08c74LL /* 563 */,
0x8852e956e1087c22LL /* 564 */, 0xa768cb8dc410ae8dLL /* 565 */,
0x38047726bfec8e1aLL /* 566 */, 0xa67738b4cd3b45aaLL /* 567 */,
0xad16691cec0dde19LL /* 568 */, 0xc6d4319380462e07LL /* 569 */,
0xc5a5876d0ba61938LL /* 570 */, 0x16b9fa1fa58fd840LL /* 571 */,
0x188ab1173ca74f18LL /* 572 */, 0xabda2f98c99c021fLL /* 573 */,
0x3e0580ab134ae816LL /* 574 */, 0x5f3b05b773645abbLL /* 575 */,
0x2501a2be5575f2f6LL /* 576 */, 0x1b2f74004e7e8ba9LL /* 577 */,
0x1cd7580371e8d953LL /* 578 */, 0x7f6ed89562764e30LL /* 579 */,
0xb15926ff596f003dLL /* 580 */, 0x9f65293da8c5d6b9LL /* 581 */,
0x6ecef04dd690f84cLL /* 582 */, 0x4782275fff33af88LL /* 583 */,
0xe41433083f820801LL /* 584 */, 0xfd0dfe409a1af9b5LL /* 585 */,
0x4325a3342cdb396bLL /* 586 */, 0x8ae77e62b301b252LL /* 587 */,
0xc36f9e9f6655615aLL /* 588 */, 0x85455a2d92d32c09LL /* 589 */,
0xf2c7dea949477485LL /* 590 */, 0x63cfb4c133a39ebaLL /* 591 */,
0x83b040cc6ebc5462LL /* 592 */, 0x3b9454c8fdb326b0LL /* 593 */,
0x56f56a9e87ffd78cLL /* 594 */, 0x2dc2940d99f42bc6LL /* 595 */,
0x98f7df096b096e2dLL /* 596 */, 0x19a6e01e3ad852bfLL /* 597 */,
0x42a99ccbdbd4b40bLL /* 598 */, 0xa59998af45e9c559LL /* 599 */,
0x366295e807d93186LL /* 600 */, 0x6b48181bfaa1f773LL /* 601 */,
0x1fec57e2157a0a1dLL /* 602 */, 0x4667446af6201ad5LL /* 603 */,
0xe615ebcacfb0f075LL /* 604 */, 0xb8f31f4f68290778LL /* 605 */,
0x22713ed6ce22d11eLL /* 606 */, 0x3057c1a72ec3c93bLL /* 607 */,
0xcb46acc37c3f1f2fLL /* 608 */, 0xdbb893fd02aaf50eLL /* 609 */,
0x331fd92e600b9fcfLL /* 610 */, 0xa498f96148ea3ad6LL /* 611 */,
0xa8d8426e8b6a83eaLL /* 612 */, 0xa089b274b7735cdcLL /* 613 */,
0x87f6b3731e524a11LL /* 614 */, 0x118808e5cbc96749LL /* 615 */,
0x9906e4c7b19bd394LL /* 616 */, 0xafed7f7e9b24a20cLL /* 617 */,
0x6509eadeeb3644a7LL /* 618 */, 0x6c1ef1d3e8ef0edeLL /* 619 */,
0xb9c97d43e9798fb4LL /* 620 */, 0xa2f2d784740c28a3LL /* 621 */,
0x7b8496476197566fLL /* 622 */, 0x7a5be3e6b65f069dLL /* 623 */,
0xf96330ed78be6f10LL /* 624 */, 0xeee60de77a076a15LL /* 625 */,
0x2b4bee4aa08b9bd0LL /* 626 */, 0x6a56a63ec7b8894eLL /* 627 */,
0x02121359ba34fef4LL /* 628 */, 0x4cbf99f8283703fcLL /* 629 */,
0x398071350caf30c8LL /* 630 */, 0xd0a77a89f017687aLL /* 631 */,
0xf1c1a9eb9e423569LL /* 632 */, 0x8c7976282dee8199LL /* 633 */,
0x5d1737a5dd1f7abdLL /* 634 */, 0x4f53433c09a9fa80LL /* 635 */,
0xfa8b0c53df7ca1d9LL /* 636 */, 0x3fd9dcbc886ccb77LL /* 637 */,
0xc040917ca91b4720LL /* 638 */, 0x7dd00142f9d1dcdfLL /* 639 */,
0x8476fc1d4f387b58LL /* 640 */, 0x23f8e7c5f3316503LL /* 641 */,
0x032a2244e7e37339LL /* 642 */, 0x5c87a5d750f5a74bLL /* 643 */,
0x082b4cc43698992eLL /* 644 */, 0xdf917becb858f63cLL /* 645 */,
0x3270b8fc5bf86ddaLL /* 646 */, 0x10ae72bb29b5dd76LL /* 647 */,
0x576ac94e7700362bLL /* 648 */, 0x1ad112dac61efb8fLL /* 649 */,
0x691bc30ec5faa427LL /* 650 */, 0xff246311cc327143LL /* 651 */,
0x3142368e30e53206LL /* 652 */, 0x71380e31e02ca396LL /* 653 */,
0x958d5c960aad76f1LL /* 654 */, 0xf8d6f430c16da536LL /* 655 */,
0xc8ffd13f1be7e1d2LL /* 656 */, 0x7578ae66004ddbe1LL /* 657 */,
0x05833f01067be646LL /* 658 */, 0xbb34b5ad3bfe586dLL /* 659 */,
0x095f34c9a12b97f0LL /* 660 */, 0x247ab64525d60ca8LL /* 661 */,
0xdcdbc6f3017477d1LL /* 662 */, 0x4a2e14d4decad24dLL /* 663 */,
0xbdb5e6d9be0a1eebLL /* 664 */, 0x2a7e70f7794301abLL /* 665 */,
0xdef42d8a270540fdLL /* 666 */, 0x01078ec0a34c22c1LL /* 667 */,
0xe5de511af4c16387LL /* 668 */, 0x7ebb3a52bd9a330aLL /* 669 */,
0x77697857aa7d6435LL /* 670 */, 0x004e831603ae4c32LL /* 671 */,
0xe7a21020ad78e312LL /* 672 */, 0x9d41a70c6ab420f2LL /* 673 */,
0x28e06c18ea1141e6LL /* 674 */, 0xd2b28cbd984f6b28LL /* 675 */,
0x26b75f6c446e9d83LL /* 676 */, 0xba47568c4d418d7fLL /* 677 */,
0xd80badbfe6183d8eLL /* 678 */, 0x0e206d7f5f166044LL /* 679 */,
0xe258a43911cbca3eLL /* 680 */, 0x723a1746b21dc0bcLL /* 681 */,
0xc7caa854f5d7cdd3LL /* 682 */, 0x7cac32883d261d9cLL /* 683 */,
0x7690c26423ba942cLL /* 684 */, 0x17e55524478042b8LL /* 685 */,
0xe0be477656a2389fLL /* 686 */, 0x4d289b5e67ab2da0LL /* 687 */,
0x44862b9c8fbbfd31LL /* 688 */, 0xb47cc8049d141365LL /* 689 */,
0x822c1b362b91c793LL /* 690 */, 0x4eb14655fb13dfd8LL /* 691 */,
0x1ecbba0714e2a97bLL /* 692 */, 0x6143459d5cde5f14LL /* 693 */,
0x53a8fbf1d5f0ac89LL /* 694 */, 0x97ea04d81c5e5b00LL /* 695 */,
0x622181a8d4fdb3f3LL /* 696 */, 0xe9bcd341572a1208LL /* 697 */,
0x1411258643cce58aLL /* 698 */, 0x9144c5fea4c6e0a4LL /* 699 */,
0x0d33d06565cf620fLL /* 700 */, 0x54a48d489f219ca1LL /* 701 */,
0xc43e5eac6d63c821LL /* 702 */, 0xa9728b3a72770dafLL /* 703 */,
0xd7934e7b20df87efLL /* 704 */, 0xe35503b61a3e86e5LL /* 705 */,
0xcae321fbc819d504LL /* 706 */, 0x129a50b3ac60bfa6LL /* 707 */,
0xcd5e68ea7e9fb6c3LL /* 708 */, 0xb01c90199483b1c7LL /* 709 */,
0x3de93cd5c295376cLL /* 710 */, 0xaed52edf2ab9ad13LL /* 711 */,
0x2e60f512c0a07884LL /* 712 */, 0xbc3d86a3e36210c9LL /* 713 */,
0x35269d9b163951ceLL /* 714 */, 0x0c7d6e2ad0cdb5faLL /* 715 */,
0x59e86297d87f5733LL /* 716 */, 0x298ef221898db0e7LL /* 717 */,
0x55000029d1a5aa7eLL /* 718 */, 0x8bc08ae1b5061b45LL /* 719 */,
0xc2c31c2b6c92703aLL /* 720 */, 0x94cc596baf25ef42LL /* 721 */,
0x0a1d73db22540456LL /* 722 */, 0x04b6a0f9d9c4179aLL /* 723 */,
0xeffdafa2ae3d3c60LL /* 724 */, 0xf7c8075bb49496c4LL /* 725 */,
0x9cc5c7141d1cd4e3LL /* 726 */, 0x78bd1638218e5534LL /* 727 */,
0xb2f11568f850246aLL /* 728 */, 0xedfabcfa9502bc29LL /* 729 */,
0x796ce5f2da23051bLL /* 730 */, 0xaae128b0dc93537cLL /* 731 */,
0x3a493da0ee4b29aeLL /* 732 */, 0xb5df6b2c416895d7LL /* 733 */,
0xfcabbd25122d7f37LL /* 734 */, 0x70810b58105dc4b1LL /* 735 */,
0xe10fdd37f7882a90LL /* 736 */, 0x524dcab5518a3f5cLL /* 737 */,
0x3c9e85878451255bLL /* 738 */, 0x4029828119bd34e2LL /* 739 */,
0x74a05b6f5d3ceccbLL /* 740 */, 0xb610021542e13ecaLL /* 741 */,
0x0ff979d12f59e2acLL /* 742 */, 0x6037da27e4f9cc50LL /* 743 */,
0x5e92975a0df1847dLL /* 744 */, 0xd66de190d3e623feLL /* 745 */,
0x5032d6b87b568048LL /* 746 */, 0x9a36b7ce8235216eLL /* 747 */,
0x80272a7a24f64b4aLL /* 748 */, 0x93efed8b8c6916f7LL /* 749 */,
0x37ddbff44cce1555LL /* 750 */, 0x4b95db5d4b99bd25LL /* 751 */,
0x92d3fda169812fc0LL /* 752 */, 0xfb1a4a9a90660bb6LL /* 753 */,
0x730c196946a4b9b2LL /* 754 */, 0x81e289aa7f49da68LL /* 755 */,
0x64669a0f83b1a05fLL /* 756 */, 0x27b3ff7d9644f48bLL /* 757 */,
0xcc6b615c8db675b3LL /* 758 */, 0x674f20b9bcebbe95LL /* 759 */,
0x6f31238275655982LL /* 760 */, 0x5ae488713e45cf05LL /* 761 */,
0xbf619f9954c21157LL /* 762 */, 0xeabac46040a8eae9LL /* 763 */,
0x454c6fe9f2c0c1cdLL /* 764 */, 0x419cf6496412691cLL /* 765 */,
0xd3dc3bef265b0f70LL /* 766 */, 0x6d0e60f5c3578a9eLL /* 767 */
};
static u64 sbox4[256] = {
0x5b0e608526323c55LL /* 768 */, 0x1a46c1a9fa1b59f5LL /* 769 */,
0xa9e245a17c4c8ffaLL /* 770 */, 0x65ca5159db2955d7LL /* 771 */,
0x05db0a76ce35afc2LL /* 772 */, 0x81eac77ea9113d45LL /* 773 */,
0x528ef88ab6ac0a0dLL /* 774 */, 0xa09ea253597be3ffLL /* 775 */,
0x430ddfb3ac48cd56LL /* 776 */, 0xc4b3a67af45ce46fLL /* 777 */,
0x4ececfd8fbe2d05eLL /* 778 */, 0x3ef56f10b39935f0LL /* 779 */,
0x0b22d6829cd619c6LL /* 780 */, 0x17fd460a74df2069LL /* 781 */,
0x6cf8cc8e8510ed40LL /* 782 */, 0xd6c824bf3a6ecaa7LL /* 783 */,
0x61243d581a817049LL /* 784 */, 0x048bacb6bbc163a2LL /* 785 */,
0xd9a38ac27d44cc32LL /* 786 */, 0x7fddff5baaf410abLL /* 787 */,
0xad6d495aa804824bLL /* 788 */, 0xe1a6a74f2d8c9f94LL /* 789 */,
0xd4f7851235dee8e3LL /* 790 */, 0xfd4b7f886540d893LL /* 791 */,
0x247c20042aa4bfdaLL /* 792 */, 0x096ea1c517d1327cLL /* 793 */,
0xd56966b4361a6685LL /* 794 */, 0x277da5c31221057dLL /* 795 */,
0x94d59893a43acff7LL /* 796 */, 0x64f0c51ccdc02281LL /* 797 */,
0x3d33bcc4ff6189dbLL /* 798 */, 0xe005cb184ce66af1LL /* 799 */,
0xff5ccd1d1db99beaLL /* 800 */, 0xb0b854a7fe42980fLL /* 801 */,
0x7bd46a6a718d4b9fLL /* 802 */, 0xd10fa8cc22a5fd8cLL /* 803 */,
0xd31484952be4bd31LL /* 804 */, 0xc7fa975fcb243847LL /* 805 */,
0x4886ed1e5846c407LL /* 806 */, 0x28cddb791eb70b04LL /* 807 */,
0xc2b00be2f573417fLL /* 808 */, 0x5c9590452180f877LL /* 809 */,
0x7a6bddfff370eb00LL /* 810 */, 0xce509e38d6d9d6a4LL /* 811 */,
0xebeb0f00647fa702LL /* 812 */, 0x1dcc06cf76606f06LL /* 813 */,
0xe4d9f28ba286ff0aLL /* 814 */, 0xd85a305dc918c262LL /* 815 */,
0x475b1d8732225f54LL /* 816 */, 0x2d4fb51668ccb5feLL /* 817 */,
0xa679b9d9d72bba20LL /* 818 */, 0x53841c0d912d43a5LL /* 819 */,
0x3b7eaa48bf12a4e8LL /* 820 */, 0x781e0e47f22f1ddfLL /* 821 */,
0xeff20ce60ab50973LL /* 822 */, 0x20d261d19dffb742LL /* 823 */,
0x16a12b03062a2e39LL /* 824 */, 0x1960eb2239650495LL /* 825 */,
0x251c16fed50eb8b8LL /* 826 */, 0x9ac0c330f826016eLL /* 827 */,
0xed152665953e7671LL /* 828 */, 0x02d63194a6369570LL /* 829 */,
0x5074f08394b1c987LL /* 830 */, 0x70ba598c90b25ce1LL /* 831 */,
0x794a15810b9742f6LL /* 832 */, 0x0d5925e9fcaf8c6cLL /* 833 */,
0x3067716cd868744eLL /* 834 */, 0x910ab077e8d7731bLL /* 835 */,
0x6a61bbdb5ac42f61LL /* 836 */, 0x93513efbf0851567LL /* 837 */,
0xf494724b9e83e9d5LL /* 838 */, 0xe887e1985c09648dLL /* 839 */,
0x34b1d3c675370cfdLL /* 840 */, 0xdc35e433bc0d255dLL /* 841 */,
0xd0aab84234131be0LL /* 842 */, 0x08042a50b48b7eafLL /* 843 */,
0x9997c4ee44a3ab35LL /* 844 */, 0x829a7b49201799d0LL /* 845 */,
0x263b8307b7c54441LL /* 846 */, 0x752f95f4fd6a6ca6LL /* 847 */,
0x927217402c08c6e5LL /* 848 */, 0x2a8ab754a795d9eeLL /* 849 */,
0xa442f7552f72943dLL /* 850 */, 0x2c31334e19781208LL /* 851 */,
0x4fa98d7ceaee6291LL /* 852 */, 0x55c3862f665db309LL /* 853 */,
0xbd0610175d53b1f3LL /* 854 */, 0x46fe6cb840413f27LL /* 855 */,
0x3fe03792df0cfa59LL /* 856 */, 0xcfe700372eb85e8fLL /* 857 */,
0xa7be29e7adbce118LL /* 858 */, 0xe544ee5cde8431ddLL /* 859 */,
0x8a781b1b41f1873eLL /* 860 */, 0xa5c94c78a0d2f0e7LL /* 861 */,
0x39412e2877b60728LL /* 862 */, 0xa1265ef3afc9a62cLL /* 863 */,
0xbcc2770c6a2506c5LL /* 864 */, 0x3ab66dd5dce1ce12LL /* 865 */,
0xe65499d04a675b37LL /* 866 */, 0x7d8f523481bfd216LL /* 867 */,
0x0f6f64fcec15f389LL /* 868 */, 0x74efbe618b5b13c8LL /* 869 */,
0xacdc82b714273e1dLL /* 870 */, 0xdd40bfe003199d17LL /* 871 */,
0x37e99257e7e061f8LL /* 872 */, 0xfa52626904775aaaLL /* 873 */,
0x8bbbf63a463d56f9LL /* 874 */, 0xf0013f1543a26e64LL /* 875 */,
0xa8307e9f879ec898LL /* 876 */, 0xcc4c27a4150177ccLL /* 877 */,
0x1b432f2cca1d3348LL /* 878 */, 0xde1d1f8f9f6fa013LL /* 879 */,
0x606602a047a7ddd6LL /* 880 */, 0xd237ab64cc1cb2c7LL /* 881 */,
0x9b938e7225fcd1d3LL /* 882 */, 0xec4e03708e0ff476LL /* 883 */,
0xfeb2fbda3d03c12dLL /* 884 */, 0xae0bced2ee43889aLL /* 885 */,
0x22cb8923ebfb4f43LL /* 886 */, 0x69360d013cf7396dLL /* 887 */,
0x855e3602d2d4e022LL /* 888 */, 0x073805bad01f784cLL /* 889 */,
0x33e17a133852f546LL /* 890 */, 0xdf4874058ac7b638LL /* 891 */,
0xba92b29c678aa14aLL /* 892 */, 0x0ce89fc76cfaadcdLL /* 893 */,
0x5f9d4e0908339e34LL /* 894 */, 0xf1afe9291f5923b9LL /* 895 */,
0x6e3480f60f4a265fLL /* 896 */, 0xeebf3a2ab29b841cLL /* 897 */,
0xe21938a88f91b4adLL /* 898 */, 0x57dfeff845c6d3c3LL /* 899 */,
0x2f006b0bf62caaf2LL /* 900 */, 0x62f479ef6f75ee78LL /* 901 */,
0x11a55ad41c8916a9LL /* 902 */, 0xf229d29084fed453LL /* 903 */,
0x42f1c27b16b000e6LL /* 904 */, 0x2b1f76749823c074LL /* 905 */,
0x4b76eca3c2745360LL /* 906 */, 0x8c98f463b91691bdLL /* 907 */,
0x14bcc93cf1ade66aLL /* 908 */, 0x8885213e6d458397LL /* 909 */,
0x8e177df0274d4711LL /* 910 */, 0xb49b73b5503f2951LL /* 911 */,
0x10168168c3f96b6bLL /* 912 */, 0x0e3d963b63cab0aeLL /* 913 */,
0x8dfc4b5655a1db14LL /* 914 */, 0xf789f1356e14de5cLL /* 915 */,
0x683e68af4e51dac1LL /* 916 */, 0xc9a84f9d8d4b0fd9LL /* 917 */,
0x3691e03f52a0f9d1LL /* 918 */, 0x5ed86e46e1878e80LL /* 919 */,
0x3c711a0e99d07150LL /* 920 */, 0x5a0865b20c4e9310LL /* 921 */,
0x56fbfc1fe4f0682eLL /* 922 */, 0xea8d5de3105edf9bLL /* 923 */,
0x71abfdb12379187aLL /* 924 */, 0x2eb99de1bee77b9cLL /* 925 */,
0x21ecc0ea33cf4523LL /* 926 */, 0x59a4d7521805c7a1LL /* 927 */,
0x3896f5eb56ae7c72LL /* 928 */, 0xaa638f3db18f75dcLL /* 929 */,
0x9f39358dabe9808eLL /* 930 */, 0xb7defa91c00b72acLL /* 931 */,
0x6b5541fd62492d92LL /* 932 */, 0x6dc6dee8f92e4d5bLL /* 933 */,
0x353f57abc4beea7eLL /* 934 */, 0x735769d6da5690ceLL /* 935 */,
0x0a234aa642391484LL /* 936 */, 0xf6f9508028f80d9dLL /* 937 */,
0xb8e319a27ab3f215LL /* 938 */, 0x31ad9c1151341a4dLL /* 939 */,
0x773c22a57bef5805LL /* 940 */, 0x45c7561a07968633LL /* 941 */,
0xf913da9e249dbe36LL /* 942 */, 0xda652d9b78a64c68LL /* 943 */,
0x4c27a97f3bc334efLL /* 944 */, 0x76621220e66b17f4LL /* 945 */,
0x967743899acd7d0bLL /* 946 */, 0xf3ee5bcae0ed6782LL /* 947 */,
0x409f753600c879fcLL /* 948 */, 0x06d09a39b5926db6LL /* 949 */,
0x6f83aeb0317ac588LL /* 950 */, 0x01e6ca4a86381f21LL /* 951 */,
0x66ff3462d19f3025LL /* 952 */, 0x72207c24ddfd3bfbLL /* 953 */,
0x4af6b6d3e2ece2ebLL /* 954 */, 0x9c994dbec7ea08deLL /* 955 */,
0x49ace597b09a8bc4LL /* 956 */, 0xb38c4766cf0797baLL /* 957 */,
0x131b9373c57c2a75LL /* 958 */, 0xb1822cce61931e58LL /* 959 */,
0x9d7555b909ba1c0cLL /* 960 */, 0x127fafdd937d11d2LL /* 961 */,
0x29da3badc66d92e4LL /* 962 */, 0xa2c1d57154c2ecbcLL /* 963 */,
0x58c5134d82f6fe24LL /* 964 */, 0x1c3ae3515b62274fLL /* 965 */,
0xe907c82e01cb8126LL /* 966 */, 0xf8ed091913e37fcbLL /* 967 */,
0x3249d8f9c80046c9LL /* 968 */, 0x80cf9bede388fb63LL /* 969 */,
0x1881539a116cf19eLL /* 970 */, 0x5103f3f76bd52457LL /* 971 */,
0x15b7e6f5ae47f7a8LL /* 972 */, 0xdbd7c6ded47e9ccfLL /* 973 */,
0x44e55c410228bb1aLL /* 974 */, 0xb647d4255edb4e99LL /* 975 */,
0x5d11882bb8aafc30LL /* 976 */, 0xf5098bbb29d3212aLL /* 977 */,
0x8fb5ea14e90296b3LL /* 978 */, 0x677b942157dd025aLL /* 979 */,
0xfb58e7c0a390acb5LL /* 980 */, 0x89d3674c83bd4a01LL /* 981 */,
0x9e2da4df4bf3b93bLL /* 982 */, 0xfcc41e328cab4829LL /* 983 */,
0x03f38c96ba582c52LL /* 984 */, 0xcad1bdbd7fd85db2LL /* 985 */,
0xbbb442c16082ae83LL /* 986 */, 0xb95fe86ba5da9ab0LL /* 987 */,
0xb22e04673771a93fLL /* 988 */, 0x845358c9493152d8LL /* 989 */,
0xbe2a488697b4541eLL /* 990 */, 0x95a2dc2dd38e6966LL /* 991 */,
0xc02c11ac923c852bLL /* 992 */, 0x2388b1990df2a87bLL /* 993 */,
0x7c8008fa1b4f37beLL /* 994 */, 0x1f70d0c84d54e503LL /* 995 */,
0x5490adec7ece57d4LL /* 996 */, 0x002b3c27d9063a3aLL /* 997 */,
0x7eaea3848030a2bfLL /* 998 */, 0xc602326ded2003c0LL /* 999 */,
0x83a7287d69a94086LL /* 1000 */, 0xc57a5fcb30f57a8aLL /* 1001 */,
0xb56844e479ebe779LL /* 1002 */, 0xa373b40f05dcbce9LL /* 1003 */,
0xd71a786e88570ee2LL /* 1004 */, 0x879cbacdbde8f6a0LL /* 1005 */,
0x976ad1bcc164a32fLL /* 1006 */, 0xab21e25e9666d78bLL /* 1007 */,
0x901063aae5e5c33cLL /* 1008 */, 0x9818b34448698d90LL /* 1009 */,
0xe36487ae3e1e8abbLL /* 1010 */, 0xafbdf931893bdcb4LL /* 1011 */,
0x6345a0dc5fbbd519LL /* 1012 */, 0x8628fe269b9465caLL /* 1013 */,
0x1e5d01603f9c51ecLL /* 1014 */, 0x4de44006a15049b7LL /* 1015 */,
0xbf6c70e5f776cbb1LL /* 1016 */, 0x411218f2ef552bedLL /* 1017 */,
0xcb0c0708705a36a3LL /* 1018 */, 0xe74d14754f986044LL /* 1019 */,
0xcd56d9430ea8280eLL /* 1020 */, 0xc12591d7535f5065LL /* 1021 */,
0xc83223f1720aef96LL /* 1022 */, 0xc3a0396f7363a51fLL /* 1023 */
};
static void
print_abc( const char *text, u64 a, u64 b, u64 c )
{
/*printf("%s: %08X%08X %08X%08X %08X%08X\n",
text,
(u32)(a>>32),
(u32)(a),
(u32)(b>>32),
(u32)(b),
(u32)(c>>32),
(u32)(c) );*/
}
static void
print_data( const char *text, u64 a, u64 b, u64 c,
u64 d, u64 e, u64 f,
u64 g, u64 h )
{
/*printf("%s: %08X%08X %08X%08X %08X%08X %08X%08X\n"
"%s %08X%08X %08X%08X %08X%08X %08X%08X\n",
text,
(u32)(a>>32),
(u32)(a),
(u32)(b>>32),
(u32)(b),
(u32)(c>>32),
(u32)(c),
(u32)(d>>32),
(u32)(d),
text,
(u32)(e>>32),
(u32)(e),
(u32)(f>>32),
(u32)(f),
(u32)(g>>32),
(u32)(g),
(u32)(h>>32),
(u32)(h) );*/
}
static void
tiger_init( TIGER_CONTEXT *hd )
{
hd->a = 0x0123456789abcdefLL;
hd->b = 0xfedcba9876543210LL;
hd->c = 0xf096a5b4c3b2e187LL;
hd->nblocks = 0;
hd->count = 0;
}
static void
round( u64 *ra, u64 *rb, u64 *rc, u64 x, int mul )
{
u64 a = *ra;
u64 b = *rb;
u64 c = *rc;
c ^= x;
a -= sbox1[ c & 0xff ] ^ sbox2[ (c >> 16) & 0xff ]
^ sbox3[ (c >> 32) & 0xff ] ^ sbox4[ (c >> 48) & 0xff ];
b += sbox4[ (c >> 8) & 0xff ] ^ sbox3[ (c >> 24) & 0xff ]
^ sbox2[ (c >> 40) & 0xff ] ^ sbox1[ (c >> 56) & 0xff ];
b *= mul;
*ra = a;
*rb = b;
*rc = c;
}
static void
pass( u64 *ra, u64 *rb, u64 *rc, u64 *x, int mul )
{
u64 a = *ra;
u64 b = *rb;
u64 c = *rc;
round( &a, &b, &c, x[0], mul );
round( &b, &c, &a, x[1], mul );
round( &c, &a, &b, x[2], mul );
round( &a, &b, &c, x[3], mul );
round( &b, &c, &a, x[4], mul );
round( &c, &a, &b, x[5], mul );
round( &a, &b, &c, x[6], mul );
round( &b, &c, &a, x[7], mul );
*ra = a;
*rb = b;
*rc = c;
}
static void
key_schedule( u64 *x )
{
x[0] -= x[7] ^ 0xa5a5a5a5a5a5a5a5LL;
x[1] ^= x[0];
x[2] += x[1];
x[3] -= x[2] ^ ((~x[1]) << 19 );
x[4] ^= x[3];
x[5] += x[4];
x[6] -= x[5] ^ ((~x[4]) >> 23 );
x[7] ^= x[6];
x[0] += x[7];
x[1] -= x[0] ^ ((~x[7]) << 19 );
x[2] ^= x[1];
x[3] += x[2];
x[4] -= x[3] ^ ((~x[2]) >> 23 );
x[5] ^= x[4];
x[6] += x[5];
x[7] -= x[6] ^ 0x0123456789abcdefLL;
}
/****************
* Transform the message DATA which consists of 512 bytes (8 words)
*/
static void
transform( TIGER_CONTEXT *hd, byte *data )
{
u64 a,b,c,aa,bb,cc;
u64 x[8];
#ifdef BIG_ENDIAN_HOST
#define MKWORD(d,n) \
( ((u64)(d)[8*(n)+7]) << 56 | ((u64)(d)[8*(n)+6]) << 48 \
| ((u64)(d)[8*(n)+5]) << 40 | ((u64)(d)[8*(n)+4]) << 32 \
| ((u64)(d)[8*(n)+3]) << 24 | ((u64)(d)[8*(n)+2]) << 16 \
| ((u64)(d)[8*(n)+1]) << 8 | ((u64)(d)[8*(n) ]) )
x[0] = MKWORD(data, 0);
x[1] = MKWORD(data, 1);
x[2] = MKWORD(data, 2);
x[3] = MKWORD(data, 3);
x[4] = MKWORD(data, 4);
x[5] = MKWORD(data, 5);
x[6] = MKWORD(data, 6);
x[7] = MKWORD(data, 7);
#undef MKWORD
#else
memcpy( &x[0], data, 64 );
#endif
/* save */
a = aa = hd->a;
b = bb = hd->b;
c = cc = hd->c;
print_data(" key0", x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7] );
print_abc(" init", a, b, c );
pass( &a, &b, &c, x, 5);
print_abc("pass1", a, b, c );
key_schedule( x );
pass( &c, &a, &b, x, 7);
print_abc("pass2", a, b, c );
key_schedule( x );
pass( &b, &c, &a, x, 9);
print_abc("pass3", a, b, c );
/* feedforward */
a ^= aa;
b -= bb;
c += cc;
/* store */
hd->a = a;
hd->b = b;
hd->c = c;
}
/* Update the message digest with the contents
* of INBUF with length INLEN.
*/
static void
tiger_write( TIGER_CONTEXT *hd, byte *inbuf, size_t inlen)
{
if( hd->count == 64 ) { /* flush the buffer */
transform( hd, hd->buf );
hd->count = 0;
hd->nblocks++;
}
if( !inbuf )
return;
if( hd->count ) {
for( ; inlen && hd->count < 64; inlen-- )
hd->buf[hd->count++] = *inbuf++;
tiger_write( hd, NULL, 0 );
if( !inlen )
return;
}
while( inlen >= 64 ) {
transform( hd, inbuf );
hd->count = 0;
hd->nblocks++;
inlen -= 64;
inbuf += 64;
}
for( ; inlen && hd->count < 64; inlen-- )
hd->buf[hd->count++] = *inbuf++;
}
/* The routine terminates the computation
*/
static void
tiger_final( TIGER_CONTEXT *hd )
{
u32 t, msb, lsb;
byte *p;
tiger_write(hd, NULL, 0); /* flush */;
msb = 0;
t = hd->nblocks;
if( (lsb = t << 6) < t ) /* multiply by 64 to make a byte count */
msb++;
msb += t >> 26;
t = lsb;
if( (lsb = t + hd->count) < t ) /* add the count */
msb++;
t = lsb;
if( (lsb = t << 3) < t ) /* multiply by 8 to make a bit count */
msb++;
msb += t >> 29;
if( hd->count < 56 ) { /* enough room */
hd->buf[hd->count++] = 0x01; /* pad */
while( hd->count < 56 )
hd->buf[hd->count++] = 0; /* pad */
}
else { /* need one extra block */
hd->buf[hd->count++] = 0x01; /* pad character */
while( hd->count < 64 )
hd->buf[hd->count++] = 0;
tiger_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 );
p = hd->buf;
#ifdef BIG_ENDIAN_HOST
#define X(a) do { *(u64*)p = hd->##a ; p += 8; } while(0)
#else /* little endian */
#define X(a) do { *p++ = hd->##a >> 56; *p++ = hd->##a >> 48; \
*p++ = hd->##a >> 40; *p++ = hd->##a >> 32; \
*p++ = hd->##a >> 24; *p++ = hd->##a >> 16; \
*p++ = hd->##a >> 8; *p++ = hd->##a; } while(0)
#endif
X(a);
X(b);
X(c);
#undef X
}
static byte *
tiger_read( TIGER_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 *
tiger_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 )
)
{
/* 40: SEQUENCE {
* 12: SEQUENCE {
* 8: OCTET STRING :54 49 47 45 52 31 39 32
* 0: NULL
* : }
* 24: OCTET STRING
* : }
*
* By replacing the 5th byte (0x04) with 0x16 we would have;
* 8: IA5String 'TIGER192'
*/
static byte asn[18] =
{ 0x30, 0x28, 0x30, 0x0c, 0x04, 0x08, 0x54, 0x49, 0x47,
0x45, 0x52, 0x31, 0x39, 0x32, 0x05, 0x00, 0x04, 0x18 };
if( algo != 6 )
return NULL;
*contextsize = sizeof(TIGER_CONTEXT);
*r_asnoid = asn;
*r_asnlen = DIM(asn);
*r_mdlen = 24;
*r_init = (void (*)(void *))tiger_init;
*r_write = (void (*)(void *, byte*, size_t))tiger_write;
*r_final = (void (*)(void *))tiger_final;
*r_read = (byte *(*)(void *))tiger_read;
return "TIGER";
}
const char * const gnupgext_version = "TIGER ($Revision$)";
static struct {
int class;
int version;
int value;
void (*func)(void);
} func_table[] = {
{ 10, 1, 0, (void(*)(void))tiger_get_info },
{ 11, 1, 6 },
};
/****************
* 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
* version = interface version of the function/pointer
* (currently this is 1 for all functions)
*/
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 ) {
/*fprintf(stderr, "failed\n");*/
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:
ret = func_table[i].func;
break;
}
i++;
} while( what && what != *class );
*sequence = i;
/*fprintf(stderr, "success\n");*/
return ret;
}
diff --git a/doc/HACKING b/doc/HACKING
index e4c1aa972..01627fe14 100644
--- a/doc/HACKING
+++ b/doc/HACKING
@@ -1,143 +1,181 @@
A Hacker's Guide to GNUPG
================================
(Some notes on GNUPG internals.)
===> Under construction <=======
CVS Access
==========
Anonymous read-only CVS access is available:
cvs -z6 -d :pserver:anonymous@ftp.guug.de:/home/koch/cvs login
use the password "anonymous". To check out the the complete
archive use:
cvs -z6 -d :pserver:anonymous@ftp.guug.de:/home/koch/cvs checkout 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
don't complain. CVS may put a high load on a server, so please don't poll
poll for new updates but wait for an anouncement; to receive this you may
want to subscribe to:
gnupg-commit-watchers@isil.d.shuttle.de
by sending a mail with "subscribe" in the body to
gnupg-commit-watchers-request@isil.d.shuttle.de
Please run scripts/autogen.sh to create some required files.
RFCs
====
1423 Privacy Enhancement for Internet Electronic Mail:
Part III: Algorithms, Modes, and Identifiers.
1489 Registration of a Cyrillic Character Set.
1750 Randomness Recommendations for Security.
1991 PGP Message Exchange Formats.
2015 MIME Security with Pretty Good Privacy (PGP).
2144 The CAST-128 Encryption Algorithm.
2279 UTF-8, a transformation format of ISO 10646.
2440 OpenPGP.
+Debug Flags
+-----------
+Use the option "--debug n" to output debug information. This option
+can be used multiple times, all values are ORed; n maybe prefixed with
+0x to use hex-values.
+
+ value used for
+ ----- ----------------------------------------------
+ 1 packet reading/writing
+ 2 MPI details
+ 4 ciphers and primes (may reveal sensitive data)
+ 8 iobuf filter functions
+ 16 iobuf stuff
+ 32 memory allocation stuff
+ 64 caching
+ 128 show memory statistics at exit
+ 256 trust verification stuff
+
+
+
+
+Directory Layout
+----------------
+ ./ Readme, configure
+ ./scripts Scripts needed by configure and others
+ ./doc Documentaion
+ ./util General purpose utility function
+ ./mpi Multi precision integer library
+ ./cipher Cryptographic functions
+ ./g10 GnuPG application
+ ./tools Some helper and demo programs
+ ./keybox The keybox library
+ ./gcrypt Stuff needed to build libgcrypt
+
+
+
+
+
Memory allocation
-----------------
Use only the functions:
m_alloc()
m_alloc_clear()
m_strdup()
m_free()
If you want to store a passphrase or some other sensitive data you may
want to use m_alloc_secure() instead of m_alloc(), as this puts the data
into a memory region which is protected from swapping (on some platforms).
m_free() works for both. This functions will not return if there is not
enough memory available.
Logging
-------
Option parsing
---------------
GNUPG does not use getopt or GNU getopt but functions of it's own. See
util/argparse.c for details. The advantage of these funtions is that
it is more easy to display and maintain the help texts for the options.
The same option table is also used to parse resource files.
What is an iobuf
----------------
This is the data structure used for most I/O of gnupg. It is similiar
to System V Streams but much simpler. It should be replaced by a cleaner
and faster implementation. We are doing to much copying and the semantics
of "filter" removing are not very clean. EOF handling is also a problem.
How to use the message digest functions
---------------------------------------
cipher/md.c implements an interface to hash (message diesgt functions).
a) If you have a common part of data and some variable parts
and you need to hash of the concatenated parts, you can use this:
md = md_open(...)
md_write( md, common_part )
md1 = md_copy( md )
md_write(md1, part1)
md_final(md1);
digest1 = md_read(md1)
md2 = md_copy( md )
md_write(md2, part2)
md_final(md2);
digest2 = md_read(md2)
An example are key signatures; the key packet is the common part
and the user-id packets are the variable parts.
b) If you need a running digest you should use this:
md = md_open(...)
md_write( md, part1 )
digest_of_part1 = md_digest( md );
md_write( md, part2 )
digest_of_part1_cat_part2 = md_digest( md );
....
Both methods may be combined. [Please see the source for the real syntax]
How to use the cipher functions
-------------------------------
How to use the public key functions
-----------------------------------
diff --git a/g10/ChangeLog b/g10/ChangeLog
index b2ccffac4..8e959a21d 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,1423 +1,1435 @@
+Wed Dec 23 13:18:14 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
+
+ * pkclist.c (add_ownertrust): Refresh validity values.
+
+ * trustdb.c (enum_cert_paths_print): New arg refresh.
+
+ * ringedit.c: Fixed problems fix keyrings
+ * parse-packet.c (dbg_parse_packet): New debug functions.
+
+ * getkey.c (getkey_disable_caches): New.
+ * import.c (import_keys): Disable caches.
+
Thu Dec 17 18:31:15 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* misc.c (trap_unaligned): Only for glibc 1
* sign.c (write_dash_escaped): Now escapes "From " lines
* g10.c: New option --escape-from-lines
* trustdb.c (sort_tsl_list): New
(list_trust_path): Now prints sorted list.
(enum_cert_paths): Likewise.
(enum_cert_paths_print): New.
(print_paths): New printing format.
* pkclist.c (add_ownertrust): New arg quit.
(edit_ownertrust): New quit selection and does not query
the recipients ownertrust anymore.
(add_ownertrust): Print the ceritficate path.
Mon Dec 14 21:18:49 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* parse-packet.c (parse_signature): Now checks for critical bit
(parse_sig_subpkt): Splitted.
(parse_one_sig_subpkt): New.
* sig-check.c (do_check): handle critical bit.
Sun Dec 13 14:10:56 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* pcklist.c (select_algo_from_prefs): Preferences should
now work (lost the != ? )
Thu Dec 10 20:15:36 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* ringedit.c (gdbm_store): Fix for inserts
* g10.c (main): New option --export-all
* export.c (export_pubkeys): New arg.
(do_export): Now may skip old keys.
* status.c: Minor patches for Sun's cc
* keygen.c (ask_algo): Disabled v3 ElGamal choice, rearranged
the numbers. Add a warning question when a sign+encrypt key
is selected.
* g10.c (do_not_use_RSA): Removed.
* misc.c (print_pubkey_algo_note): New as replacement for the
do_not_use_RSA() and chnaged all callers.
(print_cipher_algo_note): New.
(print_hash_algo_note): New.
* cipher.c (write_header): Add a call to print_cipher_algo_note.
* seckey-cert.c (protect_secret_key): Ditto
* sign.c (do_sign): Add a call to print_digest_algo_note.
* getkey.c (get_long_user_id_string): New.
* mainproc.c (check_sig_and_print): Changed the format of the
status output.
* encrypt.c (write_pubkey_enc_from_list): print used symmetric cipher.
* pkclist.c (do_we_trust): Changed a message.
Wed Dec 9 13:41:06 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* misc.c (trap_unaligned) [ALPHA]: Only if UAC_SIGBUS is defined.
* sign.c (write_dash_escaped): Add the forgotten patch by Brian Moore.
* compress.c (do_uncompress): Fixed the inflating bug.
Tue Dec 8 13:15:16 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* trustdb.c (upd_uid_record): Now uses the newest self-signature
(insert_trust_record): Now calls update with recheck set to true.
(register_trusted_key): New.
(verify_own_keys): Enhanced by list of trusted keys.
* g10.c (main): Print a warning when a devel version is used.
(main): New option --trusted-key
* import.c (merge_blocks): Fixed merging of new user ids and
added merging of subkeys.
(append_uid): Ditto.
(merge_keysig): New.
(append_key): New.
* getkey.c (merge_one_pk_and_selfsig): Get the expiration time
from the newest self-signature.
(merge_keys_and_selfsig): Ditto.
* free-packet.c (cmp_secret_key): New.
Fri Nov 27 21:37:41 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* g10.c: New option --lock-once
* tdbio.c (open_db): Add an atexit
(cleanup): New.
(tdbio_sync): Add locking.
(tdbio_end_transaction): Ditto.
(put_record_into_cache): Ditto.
* ringedit.c (keyring_copy): Ditto.
(cleanup): New.
(add_keyblock_resource): Add an atexit.
Fri Nov 27 15:30:24 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* armor.c (find_header): Another fix for clearsigs.
Fri Nov 27 12:39:29 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* status.c (display_help): Removed.
* helptext.c: New and removed the N_() from all cpr_gets.
Fri Nov 20 16:54:52 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (main): New option --not-dash-escaped
* sign.c (write_dashed_escaped): Ditto.
* armor.c (find_header): Support for NotDashEscaped header.
* getkey.c: print "disabled cache.." only if verbose is used.
Thu Nov 19 07:17:31 1998 Werner Koch <werner.koch@guug.de>
* parse-packet.c (dump_sig_subpkt): Fixed expire listing
* getkey.c (merge_keys_and_selfsig): Fixed expire calculation.
(merge_one_pk_and_selfsig): Ditto.
* keyedit.c (menu_expire). Ditto.
* keygen.c (keygen_add_key_expire): Ditto.
(ask_expire_interval): New and changed all local function to use
this instead.
(keygen_add_key_expire): Opaque should now be a public key;
changed all callers.
* parse.packet.c (parse): use skip_rest to skip packets.
* keyedit.c (keyedit_menu): New arg for cmdline cmds.
Wed Nov 18 20:33:50 1998 Werner Koch (wk@isil.d.shuttle.de)
* trustdb.c (check_trustdb): Now rechecks all gived userids.
(collect_paths): Some fixes.
(upd_pref_records): Skips empty items, evaluate all items.
* parse-packet.c (dump_sig_subpkt): Better listing of prefs.
(skip_packet): Now knows about marker packet
* g10.c: removed cmd "--edit-sig".
* pubring.asc: Updated.
Sat Nov 14 14:01:29 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (main): Changed syntax of --list-trust-path
* trustdb.c (list_trust_path): Replaced max_depth by
opt.max_cert_depth
Fri Nov 13 07:39:58 1998 Werner Koch <werner.koch@guug.de>
* trustdb.c (collect_paths): Removed a warning message.
(enum_trust_web): Removed.
(enum_cert_paths): New.
* pkclist.c (add_ownertrust): Changed to use enum_cert_paths.
(edit_ownertrust): Now list ceritficates on request.
(show_paths): New.
Wed Nov 11 18:05:44 1998 Werner Koch <werner.koch@guug.de>
* g10.c (main): New option --max-cert-depth
* tdbio.h: add new fields to ver and dir record.
* tdbio.c: read/write/dump of these fields.
(tdbio_db_matches_options): New.
* trustdb.c: replaced MAC_CERT_DEPTH by opt.max_cert_depth.
(do_check): cache validity and changed other functions
to reset the cached value.
* keylist.c (list_one): Now lists the ownertrust.
* mainproc.c (list_node): Ditto.
Tue Nov 10 10:08:59 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (g10_exit): Now looks at the new g10_errors_seen.
* mainproc.c (check_sig_and_print): Sets g10_errors_seen.
* *.c : i18n many more strings.
* ringedit.c (locate_keyblock_by_keyid): Add HAVE_LIBGDBM
(locate_keyblock_by_fpr): Ditto.
* g10.c (main): removed unsused "int errors".
(main): Add new option --charset.
* g10.c (main): special message for the unix newbie.
Mon Nov 9 07:17:42 1998 Werner Koch <werner.koch@guug.de>
* getkey.c (finish_lookup): Kludge to prefere algo 16.
* trustdb.c (new_lid_table): Clear cached item.
* status.c (cpr_get_utf8): New.
* pkclist.c (build_pk_list): Uses this.
Sun Nov 8 17:20:39 1998 Werner Koch (wk@isil.d.shuttle.de)
* mainproc.c (check_sig_and_print): Why did I use strlen()-1
in the printf? - This truncated the TZ.
Sat Nov 7 15:57:28 1998 me,,, (wk@tobold)
* getkey.c (lookup): Changes to support a read_next.
(get_pubkey): Fixed a memory leak.
* keylist.c (list_one): Now lists all matching user IDs.
Tue Nov 3 16:19:21 1998 Werner Koch (wk@isil.d.shuttle.de)
* keygen.c (ask_user_id): Now converted to UTF-8
* g10.c (main): Kludge for pgp clearsigs and textmode.
Fri Oct 30 16:40:39 1998 me,,, (wk@tobold)
* signal.c (block_all_signals): New.
(unblock_all_signals): New
* tdbio.c (tdbio_end_transaction): Now blocks all signals.
* trustdb.c (new_lid_table): Changed the representation of the
former local_lid_info stuff.
* trustdb.c (update_trust_record): Reorganized the whole thing.
* sig-check.c (check_key_signature): Now handles class 0x28
Wed Oct 28 18:56:33 1998 me,,, (wk@tobold)
* export.c (do_export): Takes care of the exportable sig flag.
Tue Oct 27 14:53:04 1998 Werner Koch (wk@isil.d.shuttle.de)
* trustdb.c (update_trust_record): New "fast" parameter.
Sun Oct 25 19:32:05 1998 Werner Koch (wk@isil.d.shuttle.de)
* openfile.c (copy_options_File): New.
* ringedit.c (add_keyblock_resource): Creates options file
* tdbio.c (tdbio_set_dbname): Ditto.
Sat Oct 24 14:10:53 1998 brian moore <bem@cmc.net>
* mainproc.c (proc_pubkey_enc): Don't release the DEK
(do_proc_packets): Ditto.
Fri Oct 23 06:49:38 1998 me,,, (wk@tobold)
* keyedit.c (keyedit_menu): Comments are now allowed
* trustdb.c: Rewrote large parts.
Thu Oct 22 15:56:45 1998 Michael Roth (mroth@nessie.de)
* encode.c: (encode_simple): Only the plain filename without
a given directory is stored in generated packets.
(encode_crypt): Ditto.
* sign.c: (sign_file) Ditto.
Thu Oct 22 10:53:41 1998 Werner Koch (wk@isil.d.shuttle.de)
* trustdb.c (update_trust_record): Add new optional arg.
* import.c (import_keys): Add statistics output
* trustdb.c (update_trustdb): Ditto.
(insert_trustdb): Ditto.
* tdbio.c (tdbio_begin_transaction): New.
(tdbio_end_transaction): New.
(tdbio_cancel_transaction): New.
* g10.c (main): New option --quit.
* trustdb.c (check_hint_sig): No tests for user-id w/o sig.
This caused an assert while checking the sigs.
* trustdb.c (upd_sig_record): Splitted into several functions.
* import.c (import_keys): New arg "fast".
* g10.c (main): New command --fast-import.
Wed Oct 21 18:19:36 1998 Michael Roth <mroth@nessie.de>
* ringedit.c (add_keyblock_resource): Directory is now created.
* tdbio.c (tdbio_set_dbname): New info message.
Wed Oct 21 11:52:04 1998 Werner Koch (wk@isil.d.shuttle.de)
* trustdb.c (update_trustdb): released keyblock in loop.
* keylist.c (list_block): New.
(list_all): Changed to use list_block.
* trustdb.c: Completed support for GDBM
* sign.c (only_old_style): Changed the way force_v3 is handled
(sign_file): Ditto.
(clearsign_file): Ditto.
* keygen.c (has_invalid_email_chars): Splitted into mailbox and
host part.
* keylist.c (list_one): Add a merge_keys_and_selfsig.
* mainproc.c (proc_tree): Ditto.
Sun Oct 18 11:49:03 1998 Werner Koch (wk@isil.d.shuttle.de)
* sign.c (only_old_style): Add option force_v3_sigs
(sign_file): Fixed a bug in sig->version
(clearsign_file): Ditto.
* parse-packet.c (dump_sig_subpkt): New
* keyedit.c (menu_expire): New.
* free-packet.c (cmp_signatures): New
Sat Oct 17 10:22:39 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c: changed output line length from 72 to 64.
* keyedit.c (fix_keyblock): New.
Fri Oct 16 10:24:47 1998 Werner Koch (wk@isil.d.shuttle.de)
* trustdb.c: Rewrote most.
* tdbio.c: Add cache and generalized hash tables.
* options.h (ENABLE_COMMENT_PACKETS): New but undef'ed.
* encode.c, sign.c, keygen.c: Disabled comment packets.
* export.c (do_export): Comment packets are never exported,
except for those in the secret keyring.
* g10.c (main): Removed option do-no-export-rsa; should be
be replaced by a secpial tool.
* export.c (do_export): Removed the code for the above option.
* armor.c (find_header): Support for new only_keyblocks.
* import.c (import_keys): Only looks for keyblock armors.
* packet.h: replaced valid_days by expiredate and changed all users.
* build-packet.c (do_public_key): calculates valid-days
(do_secret_key): Ditto.
* parse-packet.c (parse_key): expiredate is calucated from the
valid_period in v3 packets.
* keyid.c (do_fingerprint_md): calculates valid_dates.
* keygen.c (add_key_expire): fixed key expiration time for v4 packets.
* armor.c (find_header): A LF in the first 28 bytes
was skipped for non-armored data.
Thu Oct 8 11:35:51 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c (is_armored): Add test on old comment packets.
* tdbio.c (tdbio_search_dir_bypk): fixed memory leak.
* getkey.c: Changed the caching algorithms.
Wed Oct 7 19:33:28 1998 Werner Koch (wk@isil.d.shuttle.de)
* kbnodes.c (unused_nodes): New.
Wed Oct 7 11:15:36 1998 Werner Koch (wk@isil.d.shuttle.de)
* keyedit.c (sign_uids): Fixed a problem with SK which could caused
a save of an unprotected key.
(menu_adduid): Ditto.
* keyedit.c (keyedit_menu): Prefs are now correctly listed for
new user ids.
* trustdb.c (update_trust_record): New.
(insert_trust_record): Now makes use of update_trust_record.
Tue Oct 6 16:18:03 1998 Werner Koch (wk@isil.d.shuttle.de)
* trustdb.c (read_record): replaces most of the tdbio_read_records.
(write_record): Ditto.
Sat Oct 3 11:01:21 1998 Werner Koch (wk@isil.d.shuttle.de)
* keygen.c (ask_alogo): enable ElGamal enc-only only for addmode.
Wed Sep 30 10:15:33 1998 Werner Koch (wk@isil.d.shuttle.de)
* import.c (import_one): Fixed update of wrong keyblock.
Tue Sep 29 08:32:08 1998 me,,, (wk@tobold)
* mainproc.c (proc_plaintext): Display note for special filename.
* plaintext.c (handle_plaintext): Suppress output of special file.
Mon Sep 28 12:57:12 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (verify_own_keys): Add warning if a key is not protected.
* passphrase (hash_passphrase): Fixed iterated+salted mode and
setup for keysizes > hashsize.
* g10.c (main): New options: --s2k-{cipher,digest,mode}.
Fri Sep 25 09:34:23 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c: Chnaged some help texts.
Tue Sep 22 19:34:39 1998 Werner Koch (wk@isil.d.shuttle.de)
* passphrase.c (read_passphrase_from_fd): fixed bug for long
passphrases.
Mon Sep 21 11:28:05 1998 Werner Koch (wk@(none))
* getkey.c (lookup): Add code to use the sub key if the primary one
does not match the usage.
* armor.c (armor_filter): New error message: no valid data found.
(radix64_read): Changes to support multiple messages.
(i18n.h): New.
* mainproc.c (add_onepass_sig): bug fix.
Mon Sep 21 08:03:16 1998 Werner Koch (wk@isil.d.shuttle.de)
* pkclist.c (do_we_trust): Add keyid to most messages.
* passphrase.c (read_passphrase_from_fd): New.
(have_static_passphrase): New
(get_passphrase_fd): Removed.
(set_passphrase_fd): Removed.
* g10.c (main): passphrase is now read here.
* keyedit.c (keyedit_menu): "help" texts should now translate fine.
Mon Sep 21 06:40:02 1998 Werner Koch (wk@isil.d.shuttle.de)
* encode.c (encode_simple): Now disables compression
when --rfc1991 is used.
(encode_crypt): Ditto.
Fri Sep 18 16:50:32 1998 Werner Koch (wk@isil.d.shuttle.de)
* getkey.c (merge_key_and_selfsig): New.
Fri Sep 18 10:20:11 1998 Werner Koch (wk@isil.d.shuttle.de)
* pkclist.c (select_algo_from_prefs): Removed 3DES kludge.
* seskey.c (make_session_key): Fixed SERIOUS bug introduced
by adding the weak key detection code.
* sign.c (sign_file): Changed aremor header in certain cases.
Tue Sep 15 17:52:55 1998 Werner Koch (wk@isil.d.shuttle.de)
* mainproc.c (check_sig_and_print): Replaced ascime by asctimestamp.
Mon Sep 14 11:40:52 1998 Werner Koch (wk@isil.d.shuttle.de)
* seskey.c (make_session_key): Now detects weak keys.
* trustdb (clear_trust_checked_flag): New.
* plaintext.c (handle_plaintext): Does no anymore suppress CR from
cleartext signed messages.
Sun Sep 13 12:54:29 1998 Werner Koch (wk@isil.d.shuttle.de)
* trustdb.c (insert_trust_record): Fixed a stupid bug in the free
liunked list loops.
Sat Sep 12 15:49:16 1998 Werner Koch (wk@isil.d.shuttle.de)
* status.c (remove_shmid): New.
(init_shm_comprocess): Now sets permission to the real uid.
Wed Sep 9 11:15:03 1998 Werner Koch (wk@isil.d.shuttle.de)
* packet.h (PKT_pubkey_enc): New flah throw_keyid, and add logic to
implement it.
* g10.c (main): New Option --throw-keyid
* getkey.c (enum_secret_keys): Add new ar and changed all callers.
Tue Sep 8 20:04:09 1998 Werner Koch (wk@isil.d.shuttle.de)
* delkey.c (delete_key): Moved from keyedit.c.
Mon Sep 7 16:37:52 1998 Werner Koch (wk@isil.d.shuttle.de)
* build-packet.c (calc_length_header): New arg new_ctb to correctly
calculate the length of new style packets.
* armor.c (is_armored): Checks for symkey_enc packets.
* pkclist.c (select_algo_from_prefs): 3DEs substitute is now CAST5.
Tue Aug 11 17:54:50 1998 Werner Koch (wk@isil.d.shuttle.de)
* build-packet.c (do_secret_key): Fixed handling of old keys.
* getkey.c (compare_name): Fixed exact and email matching
* openfile.c (open_outfile): Changed arguments and all callers.
Tue Aug 11 09:14:35 1998 Werner Koch (wk@isil.d.shuttle.de)
* encode.c (encode_simple): Applied option set-filename and comment.
(encode_crypt): Ditto.
* sign.c (sign_file): Ditto.
* armor.c (armor_filter): Applied option comment.
* encode.c (encode_crypt): Moved init_packet to the begin.
(encode_simple): add an init_packet().
* comment (write_comment): Now enforces a hash sign as the 1st byte.
* import.c (import_one): Add explanation for "no user ids".
* compress.c (do_uncompress): Applied Brian Warner's patch to support
zlib 1.1.3 etc.
* trustdb.c (check_trust): Fixed a problem after inserting new keys.
* getkey (lookup): do not return the primary key if usage is given
(lookup_sk): Ditto and take usage into account.
* status.c (cpr_get_answer_is_yes): add display_help.
Mon Aug 10 10:11:28 1998 Werner Koch (wk@isil.d.shuttle.de)
* getkey.c (lookup_sk): Now always returns the primary if arg
primary is true.
(lookup): Likewise.
(get_pubkey_byname): Now returns the primary key
(get_seckey_byname): Ditto.
Mon Aug 10 08:34:03 1998 Werner Koch (wk@isil.d.shuttle.de)
* keyid.c (pubkey_letter): ELG_E is now a small g.
Sat Aug 8 17:26:12 1998 Werner Koch (wk@isil.d.shuttle.de)
* openfile (overwrite_filep): Changed semantics and all callers.
Sat Aug 8 12:17:07 1998 Werner Koch (wk@isil.d.shuttle.de)
* status.c (display_help): New.
Thu Aug 6 16:30:41 1998 Werner Koch,mobil,,, (wk@tobold)
* seskey.c (encode_session_key): Now uses get_random_bits().
Thu Aug 6 07:34:56 1998 Werner Koch,mobil,,, (wk@tobold)
* ringedit.c (keyring_copy): No more backupfiles for
secret keyrings and add additional warning in case of
a failed secret keyring operation.
Wed Aug 5 11:54:37 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (check_opts): Moved to main. Changed def_cipher_algo
semantics and chnaged all users.
* pubkey-enc.c (get_sssion_key): New informational output
about preferences.
* parse-packet.c (parse_symkeyenc): Fixed salted+iterated S2K
(parse_key): Ditto.
* build-packet.c (do_secret_key): Ditto.
(do_symkey_enc): Ditto.
Tue Aug 4 08:59:10 1998 Werner Koch (wk@isil.d.shuttle.de)
* getkey.c (enum_secret_keys): Now returns only primary keys.
* getkey (lookup): Now sets the new namehash field.
* parse-packet.c (parse_sig_subpkt2): New.
* sign.c (sign_file): one-pass sigs are now emiited reverse.
Preference data is considered when selecting the compress algo.
Wed Jul 29 12:53:03 1998 Werner Koch (wk@isil.d.shuttle.de)
* free-packet.c (copy_signature): New.
* keygen.c (generate_subkeypair): rewritten
* g10.c (aKeyadd): Removed option --add-key
Mon Jul 27 10:37:28 1998 Werner Koch (wk@isil.d.shuttle.de)
* seckey-cert.c (do_check): Additional check on cipher blocksize.
(protect_secret_key): Ditto.
* encr-data.c: Support for other blocksizes.
* cipher.c (write_header): Ditto.
Fri Jul 24 16:47:59 1998 Werner Koch (wk@isil.d.shuttle.de)
* kbnode.c (insert_kbnode): Changed semantics and all callers.
* keyedit.c : More or less a complete rewrite
Wed Jul 22 17:10:04 1998 Werner Koch (wk@isil.d.shuttle.de)
* build-packet.c (write_sign_packet_header): New.
Tue Jul 21 14:37:09 1998 Werner Koch (wk@isil.d.shuttle.de)
* import.c (import_one): Now creates a trustdb record.
* g10.c (main): New command --check-trustdb
Mon Jul 20 11:15:07 1998 Werner Koch (wk@isil.d.shuttle.de)
* genkey.c (generate_keypair): Default key is now DSA with
encryption only ElGamal subkey.
Thu Jul 16 10:58:33 1998 Werner Koch (wk@isil.d.shuttle.de)
* keyid.c (keyid_from_fingerprint): New.
* getkey.c (get_pubkey_byfprint): New.
Tue Jul 14 18:09:51 1998 Werner Koch (wk@isil.d.shuttle.de)
* keyid.c (fingerprint_from_pk): Add argument and changed all callers.
(fingerprint_from_sk): Ditto.
Tue Jul 14 10:10:03 1998 Werner Koch (wk@isil.d.shuttle.de)
* plaintext.c (handle_plaintext): Now returns create error if
the file could not be created or the user responded not to overwrite
the file.
* mainproc.c (proc_plaintext): Tries again if the file could not
be created to check the signature without output.
* misc.c (disable_core_dumps): New.
* g10.c (main): disable coredumps for gpg
* g10.c (MAINTAINER_OPTIONS): New to disable some options
Mon Jul 13 16:47:54 1998 Werner Koch (wk@isil.d.shuttle.de)
* plaintext.c (hash_datafiles): New arg for better support of
detached sigs. Changed all callers.
* mainproc.c (proc_signature_packets): Ditto.
* g10.c (main): New option "compress-sigs"
* sig.c (sign_file): detached signatures are not anymore compressed
unless the option --compress-sigs is used.
Thu Jul 9 19:54:54 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c: Fixes to allow zero length cleartext signatures
Thu Jul 9 14:52:47 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (build_list): Now drops setuid.
(main): Changed the way keyrings and algorithms are registered .
Wed Jul 8 14:17:30 1998 Werner Koch (wk@isil.d.shuttle.de)
* packet.h (PKT_public_key): Add field keyid.
* parse-packet.c (parse_key): Reset the above field.
* keyid.c (keyid_from_pk): Use above field as cache.
* tdbio.c, tdbio.h: New
* trustdb.c: Moved some functions to tdbio.c.
(print_keyid): New.
* pkclist.c (check_signatures_trust): New.
Wed Jul 8 10:45:28 1998 Werner Koch (wk@isil.d.shuttle.de)
* plaintext.c (special_md_putc): New.
(handle_plaintext): add clearsig argument
* mainproc.c (proc_plaintext): detection of clearsig
* sign.c (write_dased_escaped): Changed clearsig format
Tue Jul 7 18:56:19 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c (find_header): Now makes sure that there is only one
empty line for clearsigs, as this is what OP now says.
Mon Jul 6 13:09:07 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (main): New option default-secret-key
* getkey.c (get_seckey_byname): support for this option.
Mon Jul 6 09:03:49 1998 Werner Koch (wk@isil.d.shuttle.de)
* getkey.c (add_keyring): Keyrings are now added to end of the
list of keyrings. The first added keyringwill be created.
(add_secret_keyring): Likewise.
* ringedit.c (add_keyblock_resource): Files are created here.
* g10.c (aNOP): Removed
* getkey.c (lookup): Add checking of usage for name lookups
* packet.h (pubkey_usage): Add a field which may be used to store
usage capabilities.
* pkclist.c (build_pk_list): getkey now called with usage arg.
* skclist.c (build_sk_list): Ditto.
* sign.c (clearsign_file): Fixed "Hash:" headers
Sat Jul 4 13:33:31 1998 Werner Koch (wk@isil.d.shuttle.de)
* trustdb.c (list_ownertrust): New.
* g10.c (aListOwnerTrust): New.
* g10.c (def_pubkey_algo): Removed.
* trustdb.c (verify_private_data): Removed and also the call to it.
(sign_private_data): Removed.
Fri Jul 3 13:26:10 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (aEditKey): was aEditSig. Changed usage msg.
* keyedit.c: Done some i18n stuff.
* g10.c (do_not_use_RSA): New.
* sign.c (do_sign): Add call to above function.
* encode.c (write_pubkey_enc_from_list): Ditto.
Thu Jul 2 21:01:25 1998 Werner Koch (wk@isil.d.shuttle.de)
* parse-packet.c: Now is able sto store data of unknown
algorithms.
* free-packet.c: Support for this.
* build-packet.c: Can write data of packet with unknown algos.
Thu Jul 2 11:46:36 1998 Werner Koch (wk@isil.d.shuttle.de)
* parse-packet.c (parse): fixed 4 byte length header
Wed Jul 1 12:36:55 1998 Werner Koch (wk@isil.d.shuttle.de)
* packet.h (new_ctb): New field for some packets
* build-packet.c (build_packet): Support for new_ctb
* parse-packet.c (parse): Ditto.
Mon Jun 29 12:54:45 1998 Werner Koch (wk@isil.d.shuttle.de)
* packet.h: changed all "_cert" to "_key", "subcert" to "subkey".
* free-packet.c (free_packet): Removed memory leak for subkeys.
Sun Jun 28 18:32:27 1998 Werner Koch (wk@isil.d.shuttle.de)
* import.c (import_keys): Renamed from import_pubkeys.
(import_secret_one): New.
* g10.c (aExportSecret): New.
* export.c (export_seckeys): New.
* parse-packet.c (parse_certificate): Cleaned up.
(parse_packet): Trust packets are now considered as unknown.
(parse_pubkey_warning): New.
Fri Jun 26 10:37:35 1998 Werner Koch (wk@isil.d.shuttle.de)
* keygen.c (has_invalid_email_chars): New.
Wed Jun 24 16:40:22 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c (armor_filter): Now creates valid onepass_sig packets
with all detected hash algorithms.
* mainproc.c (proc_plaintext): Now uses the hash algos as specified
in the onepass_sig packets (if there are any)
Mon Jun 22 11:54:08 1998 Werner Koch (wk@isil.d.shuttle.de)
* plaintext.c (handle_plaintext): add arg to disable outout
* mainproc.c (proc_plaintext): disable output when in sigs_only mode.
Thu Jun 18 13:17:27 1998 Werner Koch (wk@isil.d.shuttle.de)
* keygen.c: Removed all rsa packet stuff, chnaged defaults
for key generation.
Sun Jun 14 21:28:31 1998 Werner Koch (wk@isil.d.shuttle.de)
* misc.c (checksum_u16): Fixed a stupid bug which caused a
wrong checksum calculation for the secret key protection and
add a backward compatibility option.
* g10.c (main): Add option --emulate-checksum-bug.
Thu Jun 11 13:26:44 1998 Werner Koch (wk@isil.d.shuttle.de)
* packet.h: Major changes to the structure of public key material
which is now stored in an array and not anaymore in a union of
algorithm specific structures. These is needed to make the system
more extendable and makes a lot of stuff much simpler. Changed
all over the system.
* dsa.c, rsa.c, elg.c: Removed.
Wed Jun 10 07:22:02 1998 Werner Koch,mobil,,, (wk@tobold)
* g10.c ("load-extension"): New option.
Mon Jun 8 22:23:37 1998 Werner Koch (wk@isil.d.shuttle.de)
* seckey-cert.c (do_check): Removed cipher constants
(protect_secret_key): Ditto.
Fri May 29 10:00:28 1998 Werner Koch (wk@isil.d.shuttle.de)
* trustdb.c (query_trust_info): New.
* keylist.c (list_one): Add output of trust info
* mainproc (list_node): ditto.
* g10.c (main): full trustdb init if -with-colons and any of the
key list modes.
Thu May 28 10:34:42 1998 Werner Koch (wk@isil.d.shuttle.de)
* status.c (STATUS_RSA_OR_IDEA): New.
* sig-check.c (check_signature): Output special status message.
* pubkey-enc.c (get_session_key): Ditto.
* mainproc.c (check_sig_and_print): Changed format of output.
* passpharse.c (passphrase_to_dek): Likewise.
Wed May 27 13:46:48 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (aListSecretKeys): New option --list-secret-keys
* keylist.c (std_key_list): Renamed to public_key_list.
(secret_key_list): New
(list_one, list_all): Add support for secret keys.
* getkey.c (get_secret_keyring): New.
* mainproc.c (list_node): Add option --with-colons for secret keys
* sig-check.c (check_key_signature): detection of selfsigs
* mainproc.c (list_node): fixed listing.
* g10.c (aListSecretKeys): New option --always-trust
* pkclist.c (do_we_trust): Override per option added
* status.c (write_status_text): Add a prefix to every output line.
Wed May 27 07:49:21 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10 (--compress-keys): New.
* options.h (compress_keys): New.
* export.c (export_pubkeys): Only compresses with the new option.
Tue May 26 11:24:33 1998 Werner Koch (wk@isil.d.shuttle.de)
* passphrase.c (get_last_passphrase): New
(set_next_passphrase): New.
(passphrase_to_dek): add support for the above functions.
* keyedit.c (make_keysig_packet): Add sigclass 0x18,
changed all callers due to a new argument.
* keygen.c (write_keybinding): New
(generate_subkeypair): Add functionality
(ask_algo, ask_keysize, ask_valid_days): Broke out of generate_keypair
(ask_user_id, ask_passphrase): Ditto.
Thu May 21 11:26:13 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c,gpgd.c (main): Does now return an int, so that egcs does
not complain.
* armor.c (fake_packet): Removed erro message and add a noticed
that this part should be fixed.
* sign.c (sign_file): Compression now comes in front of encryption.
* encode.c (encode_simple): Ditto.
(encode_crypt): Ditto.
Tue May 19 16:18:19 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c (fake_packet): Changed assertion to log_error
Sat May 16 16:02:06 1998 Werner Koch (wk@isil.d.shuttle.de)
* build-packet.c (build_packet): Add SUBKEY packets.
Fri May 15 17:57:23 1998 Werner Koch (wk@isil.d.shuttle.de)
* sign.c (hash_for): New and used in all places here.
* main.h (DEFAULT_): new macros.
* g10.c (opt.def_digest_algo): Now set to 0
* compress.c (init_compress): Add support for algo 1
* options.h (def_compress_algo): New
* g10.c (main): New option --compress-algo
Fri May 15 13:23:59 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (print_mds): New feature to print only one hash,
chnaged formatting.
Thu May 14 15:36:24 1998 Werner Koch (wk@isil.d.shuttle.de)
* misc.c (trap_unaligned) [__alpha__]: New
* g10.c (trap_unaligned): Add call to this to track down SIGBUS
on Alphas (to avoid the slow emulation code).
Wed May 13 11:48:27 1998 Werner Koch (wk@isil.d.shuttle.de)
* build-packet.c (do_signature): Support for v4 pakets.
* keyedit.c (make_keysig_packet): Ditto.
* build-packet.c (build_sig_subpkt_from_sig): New.
(build_sig_subpkt): New.
* elg.c (g10_elg_sign): removed keyid_from_skc.
* dsa.c (g10_dsa_sign): Ditto.
* rsa.c (g10_rsa_sign): Ditto.
* keyedit.c (make_keysig_packet): Add call to keyid_from_skc
* sign.c (clearsign_file): Support for v4 signatures.
(sign_file): Ditto.
Wed May 6 09:31:24 1998 Werner Koch (wk@isil.d.shuttle.de)
* parse-packet.c (do_parse): add support for 5 byte length leader.
(parse_subpkt): Ditto.
* build-packet.c (write_new_header): Ditto.
* packet.h (SIGSUBPKT_): New constants.
* parse-packet.c (parse_sig_subpkt): Changed name, made global,
and arg to return packet length, chnaged all callers
Tue May 5 22:11:59 1998 Werner Koch (wk@isil.d.shuttle.de)
* keygen.c (gen_dsa): New.
* build_packet.c (do_secret_cert): Support for DSA
Mon May 4 19:01:25 1998 Werner Koch (wk@isil.d.shuttle.de)
* compress.c: doubled buffer sizes
* parse-packet.c (do_plaintext): now uses iobuf_read/write.
Mon May 4 09:35:53 1998 Werner Koch (wk@isil.d.shuttle.de)
* seskey.c (encode_md_value): Add optional argument hash_algo,
changed all callers.
* passphrase.c (make_dek_from_passphrase): Removed
* (get_passhrase_hash): Changed name to passphrase_to_dek, add arg,
changed all callers.
* all: Introduced the new ELG identifier and added support for the
encryption only one (which is okay to use by GNUPG for signatures).
Sun May 3 17:50:26 1998 Werner Koch (wk@isil.d.shuttle.de)
* packet.h (PKT_OLD_COMMENT): New name for type 16.
* parse-packet.c (parse_comment): Now uses type 61
Fri May 1 12:44:39 1998 Werner Koch,mobil,,, (wk@tobold)
* packet.h (count): Chnaged s2k count from byte to u32.
* seckey-cert.c (do_check): Changed s2k algo 3 to 4, changed
reading of count.
* build-packet.c (do_secret_cert): ditto.
* parse-packet.c (parse_certificate): ditto.
* parse-packet.c (parse_symkeyenc): New.
* build-packet.c (do_symkey_enc): New.
Thu Apr 30 16:33:34 1998 Werner Koch (wk@isil.d.shuttle.de)
* sign.c (clearsign_file): Fixed "Hash: " armor line.
Tue Apr 28 14:27:42 1998 Werner Koch (wk@isil.d.shuttle.de)
* parse-packet.c (parse_subpkt): Some new types.
Mon Apr 27 12:53:59 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (main): Add option --skip-verify.
* mainproc.c (check_sig_and_print): Ditto.
* g10.c (print_mds): Add output for Tiger.
* sign.c (sign_file): Now uses partial length headers if used
in canonical textmode (kludge to fix a bug).
* parse-packet.c (parse_certificate): Changed BLOWFISH id.
* pubkey-enc.c (get_session_key): Ditto.
* seskey.c (make_session_key): Ditto.
* seckey-cert.c (protect_secret_key,do_check): Add BLOWFISH160.
Fri Apr 24 17:38:48 1998 Werner Koch,mobil,,, (wk@tobold)
* sig-check.c (check_key_signature): Add sig-class 0x14..0x17
* keyedit.c (sign-key): Some changes to start with support of
the above new sig-classes.
Wed Apr 22 09:01:57 1998 Werner Koch,mobil,,, (wk@tobold)
* getkey.c (compare_name): add email matching
Tue Apr 21 16:17:12 1998 Werner Koch,mobil,,, (wk@tobold)
* armor.c (armor_filter): fixed missing last LF before CSUM.
Thu Apr 9 11:35:22 1998 Werner Koch (wk@isil.d.shuttle.de)
* seckey-cert.c (do_check): New; combines all the check functions
into one.
* sign.c: removed all key management functions
* keyedit.c: New.
Thu Apr 9 09:49:36 1998 Werner Koch (wk@isil.d.shuttle.de)
* import.c (chk_self_sigs): Changed an error message.
Wed Apr 8 16:19:39 1998 Werner Koch (wk@isil.d.shuttle.de)
* packet.h: packet structs now uses structs from the pubkey,
removed all copy operations from packet to pubkey structs.
Wed Apr 8 13:40:33 1998 Werner Koch (wk@isil.d.shuttle.de)
* trustdb.c (verify_own_certs): Fixed "public key not found".
* getkey.c (key_byname): New, combines public and secret key search.
* pkclist.c (build_pkc_list): Add new arg usage, changed all callers.
* skclist.c (build_skc_list): Likewise.
* ringedit.c (find_keyblock, keyring_search2): Removed.
Wed Apr 8 09:47:21 1998 Werner Koch (wk@isil.d.shuttle.de)
* sig-check.c (do_check): Applied small fix from Ulf Möller.
Tue Apr 7 19:28:07 1998 Werner Koch (wk@isil.d.shuttle.de)
* cipher.c, encr-data.c, seckey-cert.c: Now uses cipher_xxxx
functions instead of blowfish_xxx or cast_xxx
Tue Apr 7 11:04:02 1998 Werner Koch (wk@isil.d.shuttle.de)
* Makefile.am (g10maint.o): Changed the way it is created.
Mon Apr 6 11:17:08 1998 Werner Koch (wk@isil.d.shuttle.de)
* misc.c: New.
* keygen.c (checksum,checksum_u16,checksum_mpi): Moved to misc.c
* seckey-cert.c: Kludge for wrong ELG checksum implementation.
Sat Apr 4 20:07:01 1998 Werner Koch (wk@isil.d.shuttle.de)
* cipher.c (cipher_filter): Support for CAST5
* encr-data.c (decode_filter): Ditto.
(decrypt_data): Ditto.
* seskey.c (make_session_key): Ditto.
* seckey-cert.c (check_elg, check_dsa): Ditto,
(protect_secret_key): Ditto.
* pubkey-enc.c (get_session_key): Ditto.
* passphrase.c (hash_passphrase): Ditto.
Thu Apr 2 20:22:35 1998 Werner Koch (wk@isil.d.shuttle.de)
* gpgd.c: New
Thu Apr 2 10:38:16 1998 Werner Koch (wk@isil.d.shuttle.de)
* keygen.c (generate_keypair): Add valid_days stuff.
* trustdb.c (check_trust): Add check for valid_days.
Wed Apr 1 16:15:58 1998 Werner Koch (wk@isil.d.shuttle.de)
* keygen.c (generate_keypair): Addional question whether the
selected large keysize is really needed.
Wed Apr 1 15:56:33 1998 Werner Koch (wk@isil.d.shuttle.de)
* seckey-cert.c (protect_secret_key): merged protect_xxx to here.
Wed Apr 1 10:34:46 1998 Werner Koch (wk@isil.d.shuttle.de)
* Makefile.am (g10maint.c): Changed creation rule, so that it works
on FreeBSD (missing CFLAGS).
* parse-packet.c (parse_subkey): Removed.
Thu Mar 19 15:22:36 1998 Werner Koch (wk@isil.d.shuttle.de)
* ringedit.c (keyring_enum): Fixed problem with reading too
many packets. Add support to read secret keyrings.
* getkey.c (scan_keyring): Removed
(lookup): New to replace scan_keyring.
(scan_secret_keyring): Removed.
(lookup_skc): New.
Wed Mar 18 11:47:34 1998 Werner Koch (wk@isil.d.shuttle.de)
* ringedit.c (enum_keyblocks): New read mode 11.
* keyid.c (elg_fingerprint_md): New and changed all other functions
to call this if the packet version is 4 or above.
Tue Mar 17 20:46:16 1998 Werner Koch (wk@isil.d.shuttle.de)
* parse-packet.c (parse_certificate): Add listing support for subkeys.
Tue Mar 17 20:32:22 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c (is_armored): Allow marker packet.
Thu Mar 12 13:36:49 1998 Werner Koch (wk@isil.d.shuttle.de)
* trustdb.c (check_trust): Checks timestamp of pubkey.
* sig-check. (do_check): Compares timestamps.
Tue Mar 10 17:01:56 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (main): Add call to init_signals.
* signal.c: New.
Mon Mar 9 12:43:42 1998 Werner Koch (wk@isil.d.shuttle.de)
* dsa.c: New
* packet.h, free-packet.c, parse-packet.c : Add support for DSA
* sig-check.c, getkey.c, keyid.c, ringedit.c: Ditto.
* seckey-cert.c: Ditto.
* packet.h : Moved .digest_algo of signature packets to outer
structure. Changed all references
Sun Mar 8 13:06:42 1998 Werner Koch (wk@isil.d.shuttle.de)
* openfile.c : Support for stdout filename "-".
* mainproc.c (check_sig_and_print): Enhanced status output:
* status.c (write_status_text): New.
Fri Mar 6 16:10:54 1998 Werner Koch (wk@isil.d.shuttle.de)
* kbnode.c (clone_kbnode): Fixed private_flag.
* mainproc.c (list_node): Output of string "Revoked" as user-id.
Fri Mar 6 14:26:39 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (main): Add userids to "-kv" and cleaned up this stuff.
Fri Mar 6 12:45:58 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (main): Changed semantics of the list-... commands
and added a new one. Removed option "-d"
* decrypt.c: New.
* trustdb.c (init_trustdb): Autocreate directory only if it ends
in "/.gnupg".
Thu Mar 5 12:12:11 1998 Werner Koch (wk@isil.d.shuttle.de)
* mainproc.c (do_proc_packets): New. Common part of proc_packet.
(proc_signature_packets): special version to handle signature data.
* verify.c: New.
* g10.c (aVerify): New.
* plaintext.c (hash_datafiles): New.
* compress.c (handle_compressed): Add callback arg, changed caller.
Thu Mar 5 10:20:06 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c: Is nom the common source for gpg and gpgm
* g10maint.c: Removed
* Makefile.am: Add rule to build g10maint.c
Thu Mar 5 08:43:59 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (main): Changed the way clear text sigs are faked.
Wed Mar 4 19:47:37 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10maint.c (aMuttKeyList): New
* keylist.c: New.
Wed Mar 4 17:20:33 1998 Werner Koch (wk@isil.d.shuttle.de)
* getkey.c (get_pubkey_byname): Kludge to allow 0x prefix.
Tue Mar 3 13:46:55 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10maint.c (main): New option --gen-random.
Tue Mar 3 09:50:08 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (aDeleteSecretKey): New.
(aEditSig): Add option "--edit-key" as synonym for "--edit-sig".
(aDeleteSecretKey): New.
* getkey.c (seckey_available): New.
* sign.c (delete_key): Enhanced to delete secret keys, changed all
callers.
Mon Mar 2 21:23:48 1998 Werner Koch (wk@isil.d.shuttle.de)
* pkc_list.c (build_pkc_list): Add interactive input of user ID.
Mon Mar 2 20:54:05 1998 Werner Koch (wk@isil.d.shuttle.de)
* pkclist.c (do_we_trust_pre): New.
(add_ownertrust): Add message.
* trustdb.c (enum_trust_web): Quick fix.
Mon Mar 2 13:50:53 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (main): New action aDeleteKey
* sign.c (delete_key): New.
Sun Mar 1 16:38:58 1998 Werner Koch (wk@isil.d.shuttle.de)
* trustdb.c (do_check): No returns TRUST_UNDEFINED instead of
eof error.
Fri Feb 27 18:14:03 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c (find_header): Removed trailing CR on headers.
Fri Feb 27 18:02:48 1998 Werner Koch (wk@isil.d.shuttle.de)
* ringedit.c (keyring_search) [MINGW32]: Open and close file here
because rename does not work on open files. Chnaged callers.
Fri Feb 27 16:43:11 1998 Werner Koch (wk@isil.d.shuttle.de)
* sig-check.c (do_check): Add an md_enable.
* mainproc.c (do_check_sig): Use md_open in case of detached sig
(proc_tree): Take detached sigs into account.
Fri Feb 27 15:22:46 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (main): Make use of GNUPGHOME envvar.
* g10main.c (main): Ditto.
Wed Feb 25 11:40:04 1998 Werner Koch (wk@isil.d.shuttle.de)
* plaintext.c (ask_for_detached_datafile): add opt.verbose to
info output.
* openfile.c (open_sigfile): Try also name ending in ".asc"
Wed Feb 25 08:41:00 1998 Werner Koch (wk@isil.d.shuttle.de)
* keygen.c (generate_keypair): Fixed memory overflow.
Tue Feb 24 15:51:55 1998 Werner Koch (wk@isil.d.shuttle.de)
* parse-packet.c (parse_certificate): Support for S2K.
* build-packet.c (do_secret_cert): Ditto.
* keygen.c (gen_elg): Ditto.
* seckey-cert.c (check_elg): Ditto
(protect_elg): Ditto.
* sign.c (chnage_passphrase): Ditto.
* passphrase.c (get_passphrase_hash): Support for a salt and
changed all callers.
(make_dek_from_passphrase): Ditto.
Tue Feb 24 12:30:56 1998 Werner Koch (wk@isil.d.shuttle.de)
* build-packet.c (hash_public_cert): Disabled debug output.
Fri Feb 20 17:22:28 1998 Werner Koch (wk@isil.d.shuttle.de)
* trustdb.c (init_trustdb) [MINGW32]: Removed 2nd mkdir arg.
(keyring_copy) [MINGW32]: Add a remove prior to the renames.
Wed Feb 18 18:39:02 1998 Werner Koch (wk@isil.d.shuttle.de)
* Makefile.am (OMIT_DEPENDENCIES): New.
* rsa.c: Replaced log_bug by BUG.
Wed Feb 18 13:35:58 1998 Werner Koch (wk@isil.d.shuttle.de)
* mainproc.c (do_check_sig): Now uses hash_public_cert.
* parse-packet.c (parse_certificate): Removed hashing.
* packet.h (public_cert): Removed hash variable.
* free-packet.c (copy_public_cert, free_public_cert): Likewise.
* sig-check.c (check_key_signatures): Changed semantics.
Wed Feb 18 12:11:28 1998 Werner Koch (wk@isil.d.shuttle.de)
* trustdb.c (do_check): Add handling for revocation certificates.
(build_sigrecs): Ditto.
(check_sigs): Ditto.
Wed Feb 18 09:31:04 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c (armor_filter): Add afx->hdrlines.
* revoke.c (gen_revoke): Add comment line.
* dearmor.c (enarmor_file): Ditto.
* sig-check.c (check_key_signature): Add handling for class 0x20.
* mainproc.c : Ditto.
Tue Feb 17 21:24:17 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c : Add header lines "...ARMORED FILE .."
* dearmor.c (enarmor_file): New.
* g10maint.c (main): New option "--enarmor"
Tue Feb 17 19:03:33 1998 Werner Koch (wk@isil.d.shuttle.de)
* mainproc.c : Changed a lot, because the packets are now stored
a simple linlked list and not anymore in a complicatd tree structure.
Tue Feb 17 10:14:48 1998 Werner Koch (wk@isil.d.shuttle.de)
* free_packet.c (cmp_public_certs): New.
(cmp_user_ids): New.
* kbnode.c (clone_kbnode): New.
(release_kbnode): Add clone support.
* ringedit.c (find_keyblock_bypkc): New.
* sign.c (remove_keysigs): Self signatures are now skipped,
changed arguments and all callers.
* import.c : Add functionality.
Tue Feb 17 09:31:40 1998 Werner Koch (wk@isil.d.shuttle.de)
* options.h (homedir): New option.
* g10.c, g10maint.c, getkey.c, keygen.c, trustdb.c (opt.homedir): New.
* trustdb.c (init_trustdb): mkdir for hoem directory
(sign_private_data): Renamed "sig" to "g10.sig"
Mon Feb 16 20:02:03 1998 Werner Koch (wk@isil.d.shuttle.de)
* kbnode.c (commit_kbnode): New.
(delete_kbnode): removed unused first arg. Changed all Callers.
* ringedit.c (keyblock_resource_name): New.
(get_keyblock_handle): NULL for filename returns default resource.
Mon Feb 16 19:38:48 1998 Werner Koch (wk@isil.d.shuttle.de)
* sig-check.s (check_key_signature): Now uses the supplied
public key to check the signature and not any more the one
from the getkey.c
(do_check): New.
(check_signature): Most work moved to do_check.
Mon Feb 16 14:48:57 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c (find_header): Fixed another bug.
Mon Feb 16 12:18:34 1998 Werner Koch (wk@isil.d.shuttle.de)
* getkey.c (scan_keyring): Add handling of compressed keyrings.
Mon Feb 16 10:44:51 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c, g10maint.c (strusage): Rewrote.
(build_list): New
Mon Feb 16 08:58:41 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c (use_armor): New.
Sat Feb 14 14:30:57 1998 Werner Koch (wk@isil.d.shuttle.de)
* mainproc.c (proc_tree): Sigclass fix.
Sat Feb 14 14:16:33 1998 Werner Koch (wk@isil.d.shuttle.de)
* armor.c (armor_filter): Changed version and comment string.
* encode.c, sign.c, keygen.c: Changed all comment packet strings.
Sat Feb 14 12:39:24 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (aGenRevoke): New command.
* revoke.c: New.
* sign.c (make_keysig_packet): Add support for sigclass 0x20.
Fri Feb 13 20:18:14 1998 Werner Koch (wk@isil.d.shuttle.de)
* ringedit.c (enum_keyblocks, keyring_enum): New.
Fri Feb 13 19:33:40 1998 Werner Koch (wk@isil.d.shuttle.de)
* export.c: Add functionality.
* keygen.c (generate_keypair): Moved the leading comment behind the
key packet.
* kbnode.c (walk_kbnode): Fixed.
* g10.c (main): listing armored keys now work.
Fri Feb 13 16:17:43 1998 Werner Koch (wk@isil.d.shuttle.de)
* parse-packet.c (parse_publickey, parse_signature): Fixed calls
to mpi_read used for ELG b.
Fri Feb 13 15:13:23 1998 Werner Koch (wk@isil.d.shuttle.de)
* g10.c (main): changed formatting of help output.
Thu Feb 12 22:24:42 1998 Werner Koch (wk@frodo)
* pubkey-enc.c (get_session_key): rewritten
diff --git a/g10/armor.c b/g10/armor.c
index ca74fe448..0aca33333 100644
--- a/g10/armor.c
+++ b/g10/armor.c
@@ -1,1190 +1,1190 @@
/* armor.c - Armor flter
* 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
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include "errors.h"
#include "iobuf.h"
#include "memory.h"
#include "util.h"
#include "filter.h"
#include "packet.h"
#include "options.h"
#include "main.h"
#include "status.h"
#include "i18n.h"
#define CRCINIT 0xB704CE
#define CRCPOLY 0X864CFB
#define CRCUPDATE(a,c) do { \
a = ((a) << 8) ^ crc_table[((a)&0xff >> 16) ^ (c)]; \
a &= 0x00ffffff; \
} while(0)
static u32 crc_table[256];
static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static byte asctobin[256]; /* runtime initialized */
static int is_initialized;
typedef enum {
fhdrHASArmor = 0,
fhdrNOArmor,
fhdrINIT,
fhdrINITCont,
fhdrINITSkip,
fhdrCHECKBegin,
fhdrWAITHeader,
fhdrWAITClearsig,
fhdrSKIPHeader,
fhdrCLEARSIG,
fhdrREADClearsig,
fhdrNullClearsig,
fhdrEMPTYClearsig,
fhdrCHECKClearsig,
fhdrCHECKClearsig2,
fhdrCHECKDashEscaped,
fhdrCHECKDashEscaped2,
fhdrCHECKDashEscaped3,
fhdrREADClearsigNext,
fhdrENDClearsig,
fhdrENDClearsigHelp,
fhdrTESTSpaces,
fhdrCLEARSIGSimple,
fhdrCLEARSIGSimpleNext,
fhdrTEXT,
fhdrTEXTSimple,
fhdrERROR,
fhdrERRORShow,
fhdrEOF
} fhdr_state_t;
/* if we encounter this armor string with this index, go
* into a mode which fakes packets and wait for the next armor */
#define BEGIN_SIGNED_MSG_IDX 3
static char *head_strings[] = {
"BEGIN PGP MESSAGE",
"BEGIN PGP PUBLIC KEY BLOCK",
"BEGIN PGP SIGNATURE",
"BEGIN PGP SIGNED MESSAGE",
"BEGIN PGP ARMORED FILE", /* gnupg extension */
"BEGIN PGP PRIVATE KEY BLOCK",
"BEGIN PGP SECRET KEY BLOCK", /* only used by pgp2 */
NULL
};
static char *tail_strings[] = {
"END PGP MESSAGE",
"END PGP PUBLIC KEY BLOCK",
"END PGP SIGNATURE",
"END dummy",
"END PGP ARMORED FILE",
"END PGP PRIVATE KEY BLOCK",
"END PGP SECRET KEY BLOCK",
NULL
};
static fhdr_state_t find_header( fhdr_state_t state,
byte *buf, size_t *r_buflen,
IOBUF a, size_t n,
unsigned *r_empty, int *r_hashes,
int only_keyblocks, int *not_dashed );
static void
initialize(void)
{
int i, j;
u32 t;
byte *s;
/* init the crc lookup table */
crc_table[0] = 0;
for(i=j=0; j < 128; j++ ) {
t = crc_table[j];
if( t & 0x00800000 ) {
t <<= 1;
crc_table[i++] = t ^ CRCPOLY;
crc_table[i++] = t;
}
else {
t <<= 1;
crc_table[i++] = t;
crc_table[i++] = t ^ CRCPOLY;
}
}
/* build the helptable for radix64 to bin conversion */
for(i=0; i < 256; i++ )
asctobin[i] = 255; /* used to detect invalid characters */
for(s=bintoasc,i=0; *s; s++,i++ )
asctobin[*s] = i;
is_initialized=1;
}
/****************
* Check whether this is an armored file or not
* See also parse-packet.c for details on this code
* Returns: True if it seems to be armored
*/
static int
is_armored( byte *buf )
{
int ctb, pkttype;
ctb = *buf;
if( !(ctb & 0x80) )
return 1; /* invalid packet: assume it is armored */
pkttype = ctb & 0x40 ? (ctb & 0x3f) : ((ctb>>2)&0xf);
switch( pkttype ) {
case PKT_MARKER:
case PKT_SYMKEY_ENC:
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
case PKT_PUBKEY_ENC:
case PKT_SIGNATURE:
case PKT_COMMENT:
case PKT_OLD_COMMENT:
case PKT_PLAINTEXT:
case PKT_COMPRESSED:
case PKT_ENCRYPTED:
return 0; /* seems to be a regular packet: not armored */
}
return 1;
}
/****************
* Try to check whether the iobuf is armored
* Returns true if this may be the case; the caller should use the
* filter to do further processing.
*/
int
use_armor_filter( IOBUF a )
{
byte buf[1];
int n;
n = iobuf_peek(a, buf, 1 );
if( n == -1 )
return 0; /* EOF, doesn't matter whether armored or not */
if( !n )
return 1; /* can't check it: try armored */
return is_armored(buf);
}
static void
invalid_armor(void)
{
write_status(STATUS_BADARMOR);
g10_exit(1); /* stop here */
}
/****************
* check whether the armor header is valid on a signed message.
* this is for security reasons: the header lines are not included in the
* hash and by using some creative formatting rules, Mallory could fake
* any text at the beginning of a document; assuming it is read with
* a simple viewer. We only allow the Hash Header.
*/
static int
parse_hash_header( const char *line )
{
const char *s, *s2;
unsigned found = 0;
if( strlen(line) < 6 || strlen(line) > 60 )
return 0; /* too short or too long */
if( memcmp( line, "Hash:", 5 ) )
return 0; /* invalid header */
s = line+5;
for(s=line+5;;s=s2) {
for(; *s && (*s==' ' || *s == '\t'); s++ )
;
if( !*s )
break;
for(s2=s+1; *s2 && *s2!=' ' && *s2 != '\t' && *s2 != ','; s2++ )
;
if( !strncmp( s, "RIPEMD160", s2-s ) )
found |= 1;
else if( !strncmp( s, "SHA1", s2-s ) )
found |= 2;
else if( !strncmp( s, "MD5", s2-s ) )
found |= 4;
else if( !strncmp( s, "TIGER", s2-s ) )
found |= 8;
else
return 0;
for(; *s2 && (*s2==' ' || *s2 == '\t'); s2++ )
;
if( *s2 && *s2 != ',' )
return 0;
if( *s2 )
s2++;
}
return found;
}
/****************
* parse an ascii armor.
* Returns: the state,
* the remaining bytes in BUF are returned in RBUFLEN.
* r_empty return the # of empty lines before the buffer
*/
static fhdr_state_t
find_header( fhdr_state_t state, byte *buf, size_t *r_buflen,
IOBUF a, size_t n, unsigned *r_empty, int *r_hashes,
int only_keyblocks, int *not_dashed )
{
int c=0, i;
const char *s;
byte *p;
size_t buflen;
int cont;
int clearsig=0;
int hdr_line=0;
unsigned empty = 0;
buflen = *r_buflen;
assert(buflen >= 100 );
buflen -= 4; /* reserved room for CR,LF, and two extra */
do {
switch( state ) {
case fhdrHASArmor:
/* read at least the first byte to check whether it is armored
* or not */
c = 0;
for(n=0; n < 28 && (c=iobuf_get(a)) != -1 && c != '\n'; )
buf[n++] = c;
if( !n && c == '\n' )
state = fhdrCHECKBegin;
else if( !n || c == -1 )
state = fhdrNOArmor; /* too short */
else if( !is_armored( buf ) ) {
state = fhdrNOArmor;
if( c == '\n' )
buf[n++] = c;
}
else if( c == '\n' )
state = fhdrCHECKBegin;
else
state = fhdrINITCont;
break;
case fhdrINIT: /* read some stuff into buffer */
n = 0;
case fhdrINITCont: /* read more stuff into buffer */
c = 0;
for(; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
buf[n++] = c;
state = c == '\n' ? fhdrCHECKBegin :
c == -1 ? fhdrEOF : fhdrINITSkip;
break;
case fhdrINITSkip:
if( c == '\n' )
n = 0;
else {
while( (c=iobuf_get(a)) != -1 && c != '\n' )
;
}
state = c == -1? fhdrEOF : fhdrINIT;
break;
case fhdrSKIPHeader:
while( (c=iobuf_get(a)) != -1 && c != '\n' )
;
state = c == -1? fhdrEOF : fhdrWAITHeader;
break;
case fhdrWAITHeader: /* wait for Header lines */
c = 0;
for(n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
buf[n++] = c;
buf[n] = 0;
if( n < buflen || c == '\n' ) {
if( n && buf[0] != '\r') { /* maybe a header */
if( strchr( buf, ':') ) { /* yes */
int hashes=0;
if( buf[n-1] == '\r' )
buf[--n] = 0;
if( opt.verbose ) {
log_info(_("armor header: "));
print_string( stderr, buf, n, 0 );
putc('\n', stderr);
}
if( clearsig && !(hashes=parse_hash_header( buf )) ) {
if( strlen(buf) > 15
&& !memcmp( buf, "NotDashEscaped:", 15 ) ) {
*not_dashed = 1;
state = fhdrWAITHeader;
}
else {
log_error(_("invalid clearsig header\n"));
state = fhdrERROR;
}
}
else {
state = fhdrWAITHeader;
if( r_hashes )
*r_hashes |= hashes;
}
}
else if( clearsig && n > 15 && !memcmp(buf, "-----", 5 ) )
state = fhdrNullClearsig;
else
state = fhdrCHECKDashEscaped3;
}
else if( !n || (buf[0] == '\r' && !buf[1]) ) { /* empty line */
if( clearsig )
state = fhdrWAITClearsig;
else {
/* this is not really correct: if we do not have
* a clearsig and no armor lines we are not allowed
* to have an empty line */
n = 0;
state = fhdrTEXT;
}
}
else {
log_error(_("invalid armor header: "));
print_string( stderr, buf, n, 0 );
putc('\n', stderr);
state = fhdrERROR;
}
}
else if( c != -1 ) {
if( strchr( buf, ':') ) { /* buffer to short, but this is okay*/
if( opt.verbose ) {
log_info(_("armor header: "));
print_string( stderr, buf, n, 0 );
fputs("[...]\n", stderr); /* indicate it is truncated */
}
state = fhdrSKIPHeader; /* skip rest of line */
}
else /* line too long */
state = fhdrERROR;
}
else
state = fhdrEOF;
break;
case fhdrWAITClearsig: /* skip the empty line (for clearsig) */
c = 0;
for(n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
buf[n++] = c;
if( c != -1 ) {
if( n > 15 && !memcmp(buf, "-----", 5 ) )
state = fhdrNullClearsig;
else if( c != '\n' )
state = fhdrREADClearsigNext;
else
state = fhdrCHECKDashEscaped3;
}
else {
/* fixme: we should check whether this line continues
* it is possible that we have only read ws until here
* and more stuff is to come */
state = fhdrEOF;
}
break;
case fhdrNullClearsig: /* zero length cleartext */
state = fhdrENDClearsig;
break;
case fhdrENDClearsig:
case fhdrCHECKBegin:
state = state == fhdrCHECKBegin ? fhdrINITSkip : fhdrERRORShow;
if( n < 15 )
break; /* too short */
if( memcmp( buf, "-----", 5 ) )
break;
buf[n] = 0;
p = strstr(buf+5, "-----");
if( !p )
break;
*p = 0;
p += 5;
if( *p == '\r' )
p++;
if( *p )
break; /* garbage after dashes */
p = buf+5;
for(i=0; (s=head_strings[i]); i++ )
if( !strcmp(s, p) )
break;
if( !s )
break; /* unknown begin line */
if( only_keyblocks && i != 1 && i != 5 && i != 6 )
break; /* not a keyblock armor */
/* found the begin line */
hdr_line = i;
state = fhdrWAITHeader;
if( hdr_line == BEGIN_SIGNED_MSG_IDX )
clearsig = 1;
if( opt.verbose > 1 )
log_info(_("armor: %s\n"), head_strings[hdr_line]);
break;
case fhdrCLEARSIGSimple:
/* we are at the begin of a new line */
case fhdrCLEARSIGSimpleNext:
n = 0;
c = 0;
while( n < buflen && (c=iobuf_get(a)) != -1 ) {
buf[n++] = c;
if( c == '\n' )
break;
}
buf[n] = 0;
if( c == -1 )
state = fhdrEOF;
else if( state == fhdrCLEARSIGSimple
&& n > 15 && !memcmp(buf, "-----", 5 ) ) {
if( c == '\n' )
buf[n-1] = 0;
state = fhdrENDClearsig;
}
else if( c == '\n' )
state = fhdrCLEARSIGSimple;
else
state = fhdrCLEARSIGSimpleNext;
break;
case fhdrCLEARSIG:
case fhdrEMPTYClearsig:
case fhdrREADClearsig:
/* we are at the start of a line: read a clearsig into the buffer
* we have to look for a header line or dashed escaped text*/
n = 0;
c = 0;
while( n < buflen && (c=iobuf_get(a)) != -1 && c != '\n' )
buf[n++] = c;
buf[n] = 0;
if( c == -1 )
state = fhdrEOF;
else if( !n || ( buf[0]=='\r' && !buf[1] ) ) {
state = fhdrEMPTYClearsig;
empty++;
}
else if( c == '\n' )
state = fhdrCHECKClearsig2;
else
state = fhdrCHECKClearsig;
break;
case fhdrCHECKDashEscaped3:
if( *not_dashed ) {
state = fhdrTEXTSimple;
break;
}
if( !(n > 1 && buf[0] == '-' && buf[1] == ' ' ) ) {
state = fhdrTEXT;
break;
}
/* fall through */
case fhdrCHECKDashEscaped2:
case fhdrCHECKDashEscaped:
/* check dash escaped line */
if( buf[2] == '-' || ( n > 6 && !memcmp(buf+2, "From ", 5))) {
for(i=2; i < n; i++ )
buf[i-2] = buf[i];
n -= 2;
buf[n] = 0; /* not really needed */
state = state == fhdrCHECKDashEscaped3 ? fhdrTEXT :
state == fhdrCHECKDashEscaped2 ?
fhdrREADClearsig : fhdrTESTSpaces;
}
else {
log_error(_("invalid dash escaped line: "));
print_string( stderr, buf, n, 0 );
putc('\n', stderr);
state = fhdrERROR;
}
break;
case fhdrCHECKClearsig:
/* check the clearsig line */
if( n > 15 && !memcmp(buf, "-----", 5 ) )
state = fhdrENDClearsig;
else if( buf[0] == '-' && buf[1] == ' ' && !*not_dashed )
state = fhdrCHECKDashEscaped;
else {
state = fhdrTESTSpaces;
}
break;
case fhdrCHECKClearsig2:
/* check the clearsig line */
if( n > 15 && !memcmp(buf, "-----", 5 ) )
state = fhdrENDClearsig;
else if( buf[0] == '-' && buf[1] == ' ' && !*not_dashed )
state = fhdrCHECKDashEscaped2;
else {
state = fhdrREADClearsig;
}
break;
case fhdrREADClearsigNext:
/* Read to the end of the line, do not care about checking
* for dashed escaped text of headers */
c = 0;
n = 0;
while( n < buflen && (c=iobuf_get(a)) != -1 && c != '\n' )
buf[n++] = c;
buf[n] = 0;
if( c == -1 )
state = fhdrEOF;
else if( c == '\n' )
state = fhdrREADClearsig;
else
state = fhdrTESTSpaces;
break;
case fhdrTESTSpaces: {
/* but must check whether the rest of the line
* only contains white spaces; this is problematic
* since we may have to restore the stuff. simply
* counting spaces is not enough, because it may be a
* mix of different white space characters */
IOBUF b = iobuf_temp();
while( (c=iobuf_get(a)) != -1 && c != '\n' ) {
iobuf_put(b,c);
if( c != ' ' && c != '\t' && c != '\r' )
break;
}
if( c == '\n' ) {
/* okay we can skip the rest of the line */
iobuf_close(b);
state = fhdrREADClearsig;
}
else {
iobuf_unget_and_close_temp(a,b);
state = fhdrREADClearsigNext;
}
} break;
case fhdrERRORShow:
log_error(_("invalid clear text header: "));
print_string( stderr, buf, n, 0 );
putc('\n', stderr);
state = fhdrERROR;
break;
default: BUG();
}
switch( state ) {
case fhdrINIT:
case fhdrINITCont:
case fhdrINITSkip:
case fhdrCHECKBegin:
case fhdrWAITHeader:
case fhdrWAITClearsig:
case fhdrSKIPHeader:
case fhdrEMPTYClearsig:
case fhdrCHECKClearsig:
case fhdrCHECKClearsig2:
case fhdrCHECKDashEscaped:
case fhdrCHECKDashEscaped2:
case fhdrCHECKDashEscaped3:
case fhdrTESTSpaces:
case fhdrERRORShow:
cont = 1;
break;
default: cont = 0;
}
} while( cont );
if( clearsig && state == fhdrTEXT )
state = fhdrCLEARSIG;
else if( clearsig && state == fhdrTEXTSimple ) {
state = fhdrCLEARSIGSimple;
buf[n] = '\n';
n++;
}
if( state == fhdrCLEARSIG || state == fhdrREADClearsig ) {
/* append CR,LF after removing trailing wspaces */
for(p=buf+n-1; n; n--, p-- ) {
assert( *p != '\n' );
if( *p != ' ' && *p != '\t' && *p != '\r' ) {
p[1] = '\r';
p[2] = '\n';
n += 2;
break;
}
}
if( !n ) {
buf[0] = '\r';
buf[1] = '\n';
n = 2;
}
}
*r_buflen = n;
*r_empty = empty;
return state;
}
/* figure out whether the data is armored or not */
static int
check_input( armor_filter_context_t *afx, IOBUF a )
{
int rc = 0;
size_t n;
fhdr_state_t state = afx->parse_state;
unsigned emplines;
if( state != fhdrENDClearsig )
state = fhdrHASArmor;
n = DIM(afx->helpbuf);
state = find_header( state, afx->helpbuf, &n, a,
afx->helplen, &emplines, &afx->hashes,
afx->only_keyblocks, &afx->not_dash_escaped );
switch( state ) {
case fhdrNOArmor:
afx->inp_checked = 1;
afx->inp_bypass = 1;
afx->helplen = n;
break;
case fhdrERROR:
invalid_armor();
break;
case fhdrEOF:
rc = -1;
break;
case fhdrNullClearsig:
case fhdrCLEARSIG: /* start fake package mode (for clear signatures) */
case fhdrREADClearsigNext:
case fhdrCLEARSIGSimple:
case fhdrCLEARSIGSimpleNext:
afx->helplen = n;
afx->helpidx = 0;
afx->faked = 1;
break;
case fhdrTEXT:
afx->helplen = n;
afx->helpidx = 0;
afx->inp_checked = 1;
afx->crc = CRCINIT;
afx->idx = 0;
afx->radbuf[0] = 0;
break;
default: BUG();
}
afx->parse_state = state;
return rc;
}
/* fake a literal data packet and wait for an armor line */
static int
fake_packet( armor_filter_context_t *afx, IOBUF a,
size_t *retn, byte *buf, size_t size )
{
int rc = 0;
size_t len = 0;
size_t n, nn;
fhdr_state_t state = afx->parse_state;
unsigned emplines = afx->empty;
len = 2; /* reserve 2 bytes for the length header */
size -= 3; /* and 1 for empline handling and 2 for the term header */
while( !rc && len < size ) {
if( emplines ) {
while( emplines && len < size ) {
buf[len++] = '\r';
buf[len++] = '\n';
emplines--;
}
continue;
}
if( state == fhdrENDClearsigHelp ) {
state = fhdrENDClearsig;
afx->faked = 0;
rc = -1;
continue;
}
if( state != fhdrNullClearsig
&& afx->helpidx < afx->helplen ) { /* flush the last buffer */
n = afx->helplen;
for(nn=afx->helpidx; len < size && nn < n ; nn++ )
buf[len++] = afx->helpbuf[nn];
afx->helpidx = nn;
continue;
}
if( state == fhdrEOF ) {
rc = -1;
continue;
}
/* read a new one */
n = DIM(afx->helpbuf);
afx->helpidx = 0;
state = find_header( state, afx->helpbuf, &n, a,
state == fhdrNullClearsig? afx->helplen:0,
&emplines, &afx->hashes,
afx->only_keyblocks,
&afx->not_dash_escaped );
switch( state) {
case fhdrERROR:
invalid_armor();
break;
case fhdrEOF:
rc = -1;
break;
case fhdrCLEARSIG:
BUG();
case fhdrREADClearsig:
case fhdrREADClearsigNext:
case fhdrCLEARSIGSimple:
case fhdrCLEARSIGSimpleNext:
afx->helplen = n;
break;
case fhdrENDClearsig:
state = fhdrENDClearsigHelp;
afx->helplen = n;
break;
default: BUG();
}
}
buf[0] = (len-2) >> 8;
buf[1] = (len-2);
if( state == fhdrENDClearsig ) { /* write last (ending) length header */
if( buf[0] || buf[1] ) { /* write only if length of text is > 0 */
buf[len++] = 0;
buf[len++] = 0;
}
rc = 0;
}
afx->parse_state = state;
afx->empty = emplines;
*retn = len;
return rc;
}
static int
radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
byte *buf, size_t size )
{
byte val;
int c, c2;
int checkcrc=0;
int rc = 0;
size_t n = 0;
int idx, i;
u32 crc;
crc = afx->crc;
idx = afx->idx;
val = afx->radbuf[0];
for( n=0; n < size; ) {
if( afx->helpidx < afx->helplen )
c = afx->helpbuf[afx->helpidx++];
else if( (c=iobuf_get(a)) == -1 )
break;
if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
continue;
else if( c == '=' ) { /* pad character: stop */
if( idx == 1 )
buf[n++] = val;
checkcrc++;
break;
}
else if( (c = asctobin[(c2=c)]) == 255 ) {
log_error(_("invalid radix64 character %02x skipped\n"), c2);
continue;
}
switch(idx) {
case 0: val = c << 2; break;
case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break;
case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break;
case 3: val |= c&0x3f; buf[n++] = val; break;
}
idx = (idx+1) % 4;
}
for(i=0; i < n; i++ )
crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
crc &= 0x00ffffff;
afx->crc = crc;
afx->idx = idx;
afx->radbuf[0] = val;
if( checkcrc ) {
afx->any_data = 1;
afx->inp_checked=0;
afx->faked = 0;
afx->parse_state = 0;
for(;;) { /* skip lf and pad characters */
if( afx->helpidx < afx->helplen )
c = afx->helpbuf[afx->helpidx++];
else if( (c=iobuf_get(a)) == -1 )
break;
if( c == '\n' || c == ' ' || c == '\r'
|| c == '\t' || c == '=' )
continue;
break;
}
if( c == -1 )
log_error(_("premature eof (no CRC)\n"));
else {
u32 mycrc = 0;
idx = 0;
do {
if( (c = asctobin[c]) == 255 )
break;
switch(idx) {
case 0: val = c << 2; break;
case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break;
case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break;
case 3: val |= c&0x3f; mycrc |= val; break;
}
if( afx->helpidx < afx->helplen )
c = afx->helpbuf[afx->helpidx++];
else if( (c=iobuf_get(a)) == -1 )
break;
} while( ++idx < 4 );
if( c == -1 ) {
log_error(_("premature eof (in CRC)\n"));
rc = G10ERR_INVALID_ARMOR;
}
else if( idx != 4 ) {
log_error(_("malformed CRC\n"));
rc = G10ERR_INVALID_ARMOR;
}
else if( mycrc != afx->crc ) {
log_error(_("CRC error; %06lx - %06lx\n"),
(ulong)afx->crc, (ulong)mycrc);
rc = G10ERR_INVALID_ARMOR;
}
else {
rc = 0;
#if 0
for(rc=0;!rc;) {
rc = 0 /*check_trailer( &fhdr, c )*/;
if( !rc ) {
if( afx->helpidx < afx->helplen )
c = afx->helpbuf[afx->helpidx++];
else if( (c=iobuf_get(a)) == -1 )
rc = 2;
}
}
if( rc == -1 )
rc = 0;
else if( rc == 2 ) {
log_error(_("premature eof (in Trailer)\n"));
rc = G10ERR_INVALID_ARMOR;
}
else {
log_error(_("error in trailer line\n"));
rc = G10ERR_INVALID_ARMOR;
}
#endif
}
}
}
if( !n )
rc = -1;
*retn = n;
return rc;
}
/****************
* This filter is used to handle the armor stuff
*/
int
armor_filter( void *opaque, int control,
IOBUF a, byte *buf, size_t *ret_len)
{
size_t size = *ret_len;
armor_filter_context_t *afx = opaque;
int rc=0, i, c;
byte radbuf[3];
int idx, idx2;
size_t n=0;
u32 crc;
#if 0
static FILE *fp ;
if( !fp ) {
fp = fopen("armor.out", "w");
assert(fp);
}
#endif
if( DBG_FILTER )
log_debug("armor-filter: control: %d\n", control );
if( control == IOBUFCTRL_UNDERFLOW && afx->inp_bypass ) {
for( n=0; n < size; n++ ) {
if( (c=iobuf_get(a)) == -1 )
break;
buf[n] = c & 0xff;
}
if( !n )
rc = -1;
*ret_len = n;
}
else if( control == IOBUFCTRL_UNDERFLOW ) {
if( size < 15+(4*15) ) /* need space for up to 4 onepass_sigs */
BUG(); /* supplied buffer too short */
if( afx->faked )
rc = fake_packet( afx, a, &n, buf, size );
else if( !afx->inp_checked ) {
rc = check_input( afx, a );
if( afx->inp_bypass ) {
for( n=0; n < size && n < afx->helplen; n++ )
buf[n] = afx->helpbuf[n];
if( !n )
rc = -1;
assert( n == afx->helplen );
afx->helplen = 0;
}
else if( afx->faked ) {
unsigned hashes = afx->hashes;
/* the buffer is at least 15+n*15 bytes long, so it
* is easy to construct the packets */
hashes &= 1|2|4|8;
if( !hashes )
hashes |= 4; /* default to MD 5 */
n=0;
do {
/* first some onepass signature packets */
buf[n++] = 0x90; /* old format, type 4, 1 length byte */
buf[n++] = 13; /* length */
buf[n++] = 3; /* version */
buf[n++] = 0x01; /* sigclass 0x01 (canonical text mode)*/
if( hashes & 1 ) {
hashes &= ~1;
buf[n++] = DIGEST_ALGO_RMD160;
}
else if( hashes & 2 ) {
hashes &= ~2;
buf[n++] = DIGEST_ALGO_SHA1;
}
else if( hashes & 4 ) {
hashes &= ~4;
buf[n++] = DIGEST_ALGO_MD5;
}
else if( hashes & 8 ) {
hashes &= ~8;
buf[n++] = DIGEST_ALGO_TIGER;
}
else
buf[n++] = 0; /* (don't know) */
buf[n++] = 0; /* public key algo (don't know) */
memset(buf+n, 0, 8); /* don't know the keyid */
n += 8;
buf[n++] = !hashes; /* last one */
} while( hashes );
/* followed by a plaintext packet */
buf[n++] = 0xaf; /* old packet format, type 11, var length */
buf[n++] = 0; /* set the length header */
buf[n++] = 6;
buf[n++] = 't'; /* canonical text mode */
buf[n++] = 0; /* namelength */
memset(buf+n, 0, 4); /* timestamp */
n += 4;
}
else if( !rc )
rc = radix64_read( afx, a, &n, buf, size );
}
else
rc = radix64_read( afx, a, &n, buf, size );
#if 0
if( n )
if( fwrite(buf, n, 1, fp ) != 1 )
BUG();
#endif
*ret_len = n;
}
else if( control == IOBUFCTRL_FLUSH ) {
if( !afx->status ) { /* write the header line */
if( afx->what >= DIM(head_strings) )
log_bug("afx->what=%d", afx->what);
iobuf_writestr(a, "-----");
iobuf_writestr(a, head_strings[afx->what] );
iobuf_writestr(a, "-----\n");
iobuf_writestr(a, "Version: GnuPG v" VERSION " ("
PRINTABLE_OS_NAME ")\n");
if( opt.comment_string ) {
const char *s = opt.comment_string;
iobuf_writestr(a, "Comment: " );
for( ; *s; s++ ) {
if( *s == '\n' )
iobuf_writestr(a, "\\n" );
else if( *s == '\r' )
iobuf_writestr(a, "\\r" );
else if( *s == '\v' )
iobuf_writestr(a, "\\v" );
else
iobuf_put(a, *s );
}
iobuf_put(a, '\n' );
}
else
iobuf_writestr(a,
"Comment: For info see www.gnupg.org");
if( afx->hdrlines )
iobuf_writestr(a, afx->hdrlines);
iobuf_put(a, '\n');
afx->status++;
afx->idx = 0;
afx->idx2 = 0;
afx->crc = CRCINIT;
}
crc = afx->crc;
idx = afx->idx;
idx2 = afx->idx2;
for(i=0; i < idx; i++ )
radbuf[i] = afx->radbuf[i];
for(i=0; i < size; i++ )
crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
crc &= 0x00ffffff;
for( ; size; buf++, size-- ) {
radbuf[idx++] = *buf;
if( idx > 2 ) {
idx = 0;
c = bintoasc[(*radbuf >> 2) & 077];
iobuf_put(a, c);
c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
iobuf_put(a, c);
c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
iobuf_put(a, c);
c = bintoasc[radbuf[2]&077];
iobuf_put(a, c);
if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
iobuf_put(a, '\n');
idx2=0;
}
}
}
for(i=0; i < idx; i++ )
afx->radbuf[i] = radbuf[i];
afx->idx = idx;
afx->idx2 = idx2;
afx->crc = crc;
}
else if( control == IOBUFCTRL_INIT ) {
if( !is_initialized )
initialize();
}
else if( control == IOBUFCTRL_FREE ) {
if( afx->status ) { /* pad, write cecksum, and bottom line */
crc = afx->crc;
idx = afx->idx;
idx2 = afx->idx2;
for(i=0; i < idx; i++ )
radbuf[i] = afx->radbuf[i];
if( idx ) {
c = bintoasc[(*radbuf>>2)&077];
iobuf_put(a, c);
if( idx == 1 ) {
c = bintoasc[((*radbuf << 4) & 060) & 077];
iobuf_put(a, c);
iobuf_put(a, '=');
iobuf_put(a, '=');
}
else { /* 2 */
c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1]>>4)&017))&077];
iobuf_put(a, c);
c = bintoasc[((radbuf[1] << 2) & 074) & 077];
iobuf_put(a, c);
iobuf_put(a, '=');
}
if( ++idx2 >= (64/4) ) { /* pgp doesn't like 72 here */
iobuf_put(a, '\n');
idx2=0;
}
}
/* may need a linefeed */
if( idx2 )
iobuf_put(a, '\n');
/* write the CRC */
iobuf_put(a, '=');
radbuf[0] = crc >>16;
radbuf[1] = crc >> 8;
radbuf[2] = crc;
c = bintoasc[(*radbuf >> 2) & 077];
iobuf_put(a, c);
c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
iobuf_put(a, c);
c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
iobuf_put(a, c);
c = bintoasc[radbuf[2]&077];
iobuf_put(a, c);
iobuf_put(a, '\n');
/* and the the trailer */
if( afx->what >= DIM(tail_strings) )
log_bug("afx->what=%d", afx->what);
iobuf_writestr(a, "-----");
iobuf_writestr(a, tail_strings[afx->what] );
iobuf_writestr(a, "-----\n");
}
else if( !afx->any_data && !afx->inp_bypass )
- log_error(_("no valid RFC1991 or OpenPGP data found.\n"));
+ log_error(_("no valid OpenPGP data found.\n"));
}
else if( control == IOBUFCTRL_DESC )
*(char**)buf = "armor_filter";
return rc;
}
diff --git a/g10/build-packet.c b/g10/build-packet.c
index d83568328..5b952f153 100644
--- a/g10/build-packet.c
+++ b/g10/build-packet.c
@@ -1,901 +1,901 @@
/* build-packet.c - assemble packets and write them
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "packet.h"
#include "errors.h"
#include "iobuf.h"
#include "mpi.h"
#include "util.h"
#include "cipher.h"
#include "memory.h"
#include "options.h"
static int do_comment( IOBUF out, int ctb, PKT_comment *rem );
static int do_user_id( IOBUF out, int ctb, PKT_user_id *uid );
static int do_public_key( IOBUF out, int ctb, PKT_public_key *pk );
static int do_secret_key( IOBUF out, int ctb, PKT_secret_key *pk );
static int do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc );
static int do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc );
static u32 calc_plaintext( PKT_plaintext *pt );
static int do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt );
static int do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed );
static int do_compressed( IOBUF out, int ctb, PKT_compressed *cd );
static int do_signature( IOBUF out, int ctb, PKT_signature *sig );
static int do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops );
static int calc_header_length( u32 len, int new_ctb );
static int write_16(IOBUF inp, u16 a);
static int write_32(IOBUF inp, u32 a);
static int write_header( IOBUF out, int ctb, u32 len );
static int write_sign_packet_header( IOBUF out, int ctb, u32 len );
static int write_header2( IOBUF out, int ctb, u32 len, int hdrlen, int blkmode );
static int write_new_header( IOBUF out, int ctb, u32 len, int hdrlen );
static int write_version( IOBUF out, int ctb );
/****************
* Build a packet and write it to INP
* Returns: 0 := okay
* >0 := error
* Note: Caller must free the packet
*/
int
build_packet( IOBUF out, PACKET *pkt )
{
int new_ctb=0, rc=0, ctb;
if( DBG_PACKET )
log_debug("build_packet() type=%d\n", pkt->pkttype );
assert( pkt->pkt.generic );
switch( pkt->pkttype ) {
case PKT_OLD_COMMENT: pkt->pkttype = PKT_COMMENT; break;
case PKT_PLAINTEXT: new_ctb = pkt->pkt.plaintext->new_ctb; break;
case PKT_ENCRYPTED: new_ctb = pkt->pkt.encrypted->new_ctb; break;
case PKT_COMPRESSED:new_ctb = pkt->pkt.compressed->new_ctb; break;
default: break;
}
if( new_ctb || pkt->pkttype > 15 ) /* new format */
ctb = 0xc0 | (pkt->pkttype & 0x3f);
else
ctb = 0x80 | ((pkt->pkttype & 15)<<2);
switch( pkt->pkttype ) {
case PKT_USER_ID:
rc = do_user_id( out, ctb, pkt->pkt.user_id );
break;
case PKT_COMMENT:
rc = do_comment( out, ctb, pkt->pkt.comment );
break;
case PKT_PUBLIC_SUBKEY:
case PKT_PUBLIC_KEY:
rc = do_public_key( out, ctb, pkt->pkt.public_key );
break;
case PKT_SECRET_SUBKEY:
case PKT_SECRET_KEY:
rc = do_secret_key( out, ctb, pkt->pkt.secret_key );
break;
case PKT_SYMKEY_ENC:
rc = do_symkey_enc( out, ctb, pkt->pkt.symkey_enc );
break;
case PKT_PUBKEY_ENC:
rc = do_pubkey_enc( out, ctb, pkt->pkt.pubkey_enc );
break;
case PKT_PLAINTEXT:
rc = do_plaintext( out, ctb, pkt->pkt.plaintext );
break;
case PKT_ENCRYPTED:
rc = do_encrypted( out, ctb, pkt->pkt.encrypted );
break;
case PKT_COMPRESSED:
rc = do_compressed( out, ctb, pkt->pkt.compressed );
break;
case PKT_SIGNATURE:
rc = do_signature( out, ctb, pkt->pkt.signature );
break;
case PKT_ONEPASS_SIG:
rc = do_onepass_sig( out, ctb, pkt->pkt.onepass_sig );
break;
case PKT_RING_TRUST:
default:
log_bug("invalid packet type in build_packet()\n");
break;
}
return rc;
}
/****************
* calculate the length of a packet described by PKT
*/
u32
calc_packet_length( PACKET *pkt )
{
u32 n=0;
int new_ctb = 0;
assert( pkt->pkt.generic );
switch( pkt->pkttype ) {
case PKT_PLAINTEXT:
n = calc_plaintext( pkt->pkt.plaintext );
new_ctb = pkt->pkt.plaintext->new_ctb;
break;
case PKT_USER_ID:
case PKT_COMMENT:
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
case PKT_SYMKEY_ENC:
case PKT_PUBKEY_ENC:
case PKT_ENCRYPTED:
case PKT_SIGNATURE:
case PKT_ONEPASS_SIG:
case PKT_RING_TRUST:
case PKT_COMPRESSED:
default:
log_bug("invalid packet type in calc_packet_length()");
break;
}
n += calc_header_length(n, new_ctb);
return n;
}
static void
write_fake_data( IOBUF out, MPI a )
{
byte *s;
u16 len;
if( a ) {
s = (byte*)a;
len = (s[0] << 8) | s[1];
iobuf_write( out, s+2, len );
}
}
static int
do_comment( IOBUF out, int ctb, PKT_comment *rem )
{
if( !opt.no_comment ) {
write_header(out, ctb, rem->len);
if( iobuf_write( out, rem->data, rem->len ) )
return G10ERR_WRITE_FILE;
}
return 0;
}
static int
do_user_id( IOBUF out, int ctb, PKT_user_id *uid )
{
write_header(out, ctb, uid->len);
if( iobuf_write( out, uid->name, uid->len ) )
return G10ERR_WRITE_FILE;
return 0;
}
static int
do_public_key( IOBUF out, int ctb, PKT_public_key *pk )
{
int rc = 0;
int n, i;
IOBUF a = iobuf_temp();
if( !pk->version )
iobuf_put( a, 3 );
else
iobuf_put( a, pk->version );
write_32(a, pk->timestamp );
if( pk->version < 4 ) {
u16 ndays;
if( pk->expiredate )
ndays = (u16)((pk->expiredate - pk->timestamp) / 86400L);
else
ndays = 0;
write_16(a, ndays );
}
iobuf_put(a, pk->pubkey_algo );
n = pubkey_get_npkey( pk->pubkey_algo );
if( !n )
write_fake_data( a, pk->pkey[0] );
for(i=0; i < n; i++ )
mpi_write(a, pk->pkey[i] );
write_header2(out, ctb, iobuf_get_temp_length(a), pk->hdrbytes, 1 );
if( iobuf_write_temp( out, a ) )
rc = G10ERR_WRITE_FILE;
iobuf_close(a);
return rc;
}
/****************
* Make a hash value from the public key certificate
*/
void
hash_public_key( MD_HANDLE md, PKT_public_key *pk )
{
PACKET pkt;
int rc = 0;
int c;
IOBUF a = iobuf_temp();
#if 0
FILE *fp = fopen("dump.pk", "a");
int i=0;
fprintf(fp, "\nHashing PK (v%d):\n", pk->version);
#endif
/* build the packet */
init_packet(&pkt);
pkt.pkttype = PKT_PUBLIC_KEY;
pkt.pkt.public_key = pk;
if( (rc = build_packet( a, &pkt )) )
log_fatal("build public_key for hashing failed: %s\n", g10_errstr(rc));
while( (c=iobuf_get(a)) != -1 ) {
#if 0
fprintf( fp," %02x", c );
if( (++i == 24) ) {
putc('\n', fp);
i=0;
}
#endif
md_putc( md, c );
}
#if 0
putc('\n', fp);
fclose(fp);
#endif
iobuf_cancel(a);
}
static int
do_secret_key( IOBUF out, int ctb, PKT_secret_key *sk )
{
int rc = 0;
int i, nskey, npkey;
IOBUF a = iobuf_temp();
if( !sk->version )
iobuf_put( a, 3 );
else
iobuf_put( a, sk->version );
write_32(a, sk->timestamp );
if( sk->version < 4 ) {
u16 ndays;
if( sk->expiredate )
ndays = (u16)((sk->expiredate - sk->timestamp) / 86400L);
else
ndays = 0;
write_16(a, 0 );
}
iobuf_put(a, sk->pubkey_algo );
nskey = pubkey_get_nskey( sk->pubkey_algo );
npkey = pubkey_get_npkey( sk->pubkey_algo );
if( !npkey ) {
write_fake_data( a, sk->skey[0] );
goto leave;
}
assert( npkey < nskey );
for(i=0; i < npkey; i++ )
mpi_write(a, sk->skey[i] );
if( sk->is_protected ) {
if( is_RSA(sk->pubkey_algo) && sk->version < 4
&& !sk->protect.s2k.mode ) {
iobuf_put(a, sk->protect.algo );
iobuf_write(a, sk->protect.iv, 8 );
}
else {
iobuf_put(a, 0xff );
iobuf_put(a, sk->protect.algo );
iobuf_put(a, sk->protect.s2k.mode );
iobuf_put(a, sk->protect.s2k.hash_algo );
if( sk->protect.s2k.mode == 1
|| sk->protect.s2k.mode == 3 )
iobuf_write(a, sk->protect.s2k.salt, 8 );
if( sk->protect.s2k.mode == 3 )
iobuf_put(a, sk->protect.s2k.count );
iobuf_write(a, sk->protect.iv, 8 );
}
}
else
iobuf_put(a, 0 );
if( sk->is_protected && sk->version >= 4 ) {
byte *p;
assert( mpi_is_opaque( sk->skey[npkey] ) );
p = mpi_get_opaque( sk->skey[npkey], &i );
iobuf_write(a, p, i );
}
else {
for( ; i < nskey; i++ )
mpi_write(a, sk->skey[i] );
write_16(a, sk->csum );
}
leave:
write_header2(out, ctb, iobuf_get_temp_length(a), sk->hdrbytes, 1 );
if( iobuf_write_temp( out, a ) )
rc = G10ERR_WRITE_FILE;
iobuf_close(a);
return rc;
}
static int
do_symkey_enc( IOBUF out, int ctb, PKT_symkey_enc *enc )
{
int rc = 0;
IOBUF a = iobuf_temp();
assert( enc->version == 4 );
switch( enc->s2k.mode ) {
case 0: case 1: case 3: break;
default: log_bug("do_symkey_enc: s2k=%d\n", enc->s2k.mode );
}
iobuf_put( a, enc->version );
iobuf_put( a, enc->cipher_algo );
iobuf_put( a, enc->s2k.mode );
iobuf_put( a, enc->s2k.hash_algo );
if( enc->s2k.mode == 1 || enc->s2k.mode == 3 ) {
iobuf_write(a, enc->s2k.salt, 8 );
if( enc->s2k.mode == 3 )
iobuf_put(a, enc->s2k.count);
}
if( enc->seskeylen )
iobuf_write(a, enc->seskey, enc->seskeylen );
write_header(out, ctb, iobuf_get_temp_length(a) );
if( iobuf_write_temp( out, a ) )
rc = G10ERR_WRITE_FILE;
iobuf_close(a);
return rc;
}
static int
do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
{
int rc = 0;
int n, i;
IOBUF a = iobuf_temp();
write_version( a, ctb );
if( enc->throw_keyid ) {
write_32(a, 0 ); /* don't tell Eve who can decrypt the message */
write_32(a, 0 );
}
else {
write_32(a, enc->keyid[0] );
write_32(a, enc->keyid[1] );
}
iobuf_put(a,enc->pubkey_algo );
n = pubkey_get_nenc( enc->pubkey_algo );
if( !n )
write_fake_data( a, enc->data[0] );
for(i=0; i < n; i++ )
mpi_write(a, enc->data[i] );
write_header(out, ctb, iobuf_get_temp_length(a) );
if( iobuf_write_temp( out, a ) )
rc = G10ERR_WRITE_FILE;
iobuf_close(a);
return rc;
}
static u32
calc_plaintext( PKT_plaintext *pt )
{
return pt->len? (1 + 1 + pt->namelen + 4 + pt->len) : 0;
}
static int
do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt )
{
int i, rc = 0;
u32 n;
byte buf[1000]; /* FIXME: this buffer has the plaintext! */
int nbytes;
write_header(out, ctb, calc_plaintext( pt ) );
iobuf_put(out, pt->mode );
iobuf_put(out, pt->namelen );
for(i=0; i < pt->namelen; i++ )
iobuf_put(out, pt->name[i] );
if( write_32(out, pt->timestamp ) )
rc = G10ERR_WRITE_FILE;
n = 0;
while( (nbytes=iobuf_read(pt->buf, buf, 1000)) != -1 ) {
if( iobuf_write(out, buf, nbytes) == -1 ) {
rc = G10ERR_WRITE_FILE;
break;
}
n += nbytes;
}
memset(buf,0,1000); /* at least burn the buffer */
if( !pt->len )
iobuf_set_block_mode(out, 0 ); /* write end marker */
else if( n != pt->len )
log_error("do_plaintext(): wrote %lu bytes but expected %lu bytes\n",
(ulong)n, (ulong)pt->len );
return rc;
}
static int
do_encrypted( IOBUF out, int ctb, PKT_encrypted *ed )
{
int rc = 0;
u32 n;
n = ed->len ? (ed->len + 10) : 0;
write_header(out, ctb, n );
/* This is all. The caller has to write the real data */
return rc;
}
static int
do_compressed( IOBUF out, int ctb, PKT_compressed *cd )
{
int rc = 0;
/* we must use the old convention and don't use blockmode */
write_header2(out, ctb, 0, 0, 0 );
iobuf_put(out, cd->algorithm );
/* This is all. The caller has to write the real data */
return rc;
}
/****************
* Find a subpacket of type REQTYPE in BUFFER and a return a pointer
* to the first byte of that subpacket data.
* And return the length of the packet in RET_N and the number of
* header bytes in RET_HLEN (length header and type byte).
*/
byte *
find_subpkt( byte *buffer, sigsubpkttype_t reqtype,
size_t *ret_hlen, size_t *ret_n )
{
int buflen;
sigsubpkttype_t type;
byte *bufstart;
size_t n;
if( !buffer )
return NULL;
buflen = (*buffer << 8) | buffer[1];
buffer += 2;
for(;;) {
if( !buflen )
return NULL; /* end of packets; not found */
bufstart = buffer;
n = *buffer++; buflen--;
if( n == 255 ) {
if( buflen < 4 )
break;
n = (buffer[0] << 24) | (buffer[1] << 16)
| (buffer[2] << 8) | buffer[3];
buffer += 4;
buflen -= 4;
}
else if( n >= 192 ) {
if( buflen < 2 )
break;
n = (( n - 192 ) << 8) + *buffer + 192;
buflen--;
}
if( buflen < n )
break;
type = *buffer & 0x7f;
if( type == reqtype ) {
buffer++;
n--;
if( n > buflen )
break;
if( ret_hlen )
*ret_hlen = buffer - bufstart;
if( ret_n )
*ret_n = n;
return buffer;
}
buffer += n; buflen -=n;
}
log_error("find_subpkt: buffer shorter than subpacket\n");
return NULL;
}
/****************
* Create or update a signature subpacket for SIG of TYPE.
* This functions know, where to put the data (hashed or unhashed).
* The function may move data from the unhased part to the hashed one.
* Note: All pointers into sig->[un]hashed are not valid after a call
* to this function. The data to but into the subpaket should be
* in buffer with a length of buflen.
*/
void
build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
const byte *buffer, size_t buflen )
{
byte *data;
size_t hlen, dlen;
int found, hashed, realloced;
size_t n, n0;
if( (data = find_subpkt( sig->hashed_data, type, &hlen, &dlen )) )
found = 1;
else if( (data = find_subpkt( sig->unhashed_data, type, &hlen, &dlen )))
found = 2;
else
found = 0;
if( found )
log_bug("build_sig_packet: update nyi\n");
if( buflen+1 >= 192 )
log_bug("build_sig_packet: long subpackets are nyi\n");
switch( type ) {
case SIGSUBPKT_SIG_CREATED:
case SIGSUBPKT_PRIV_ADD_SIG:
case SIGSUBPKT_PREF_SYM:
case SIGSUBPKT_PREF_HASH:
case SIGSUBPKT_PREF_COMPR:
case SIGSUBPKT_KS_FLAGS:
case SIGSUBPKT_KEY_EXPIRE:
hashed = 1; break;
default: hashed = 0; break;
}
if( hashed ) {
n0 = sig->hashed_data ? ((*sig->hashed_data << 8)
| sig->hashed_data[1]) : 0;
n = n0 + 1 + 1 + buflen; /* length, type, buffer */
realloced = !!sig->hashed_data;
data = sig->hashed_data ? m_realloc( sig->hashed_data, n+2 )
: m_alloc( n+2 );
}
else {
n0 = sig->unhashed_data ? ((*sig->unhashed_data << 8)
| sig->unhashed_data[1]) : 0;
n = n0 + 1 + 1 + buflen; /* length, type, buffer */
realloced = !!sig->unhashed_data;
data = sig->unhashed_data ? m_realloc( sig->unhashed_data, n+2 )
: m_alloc( n+2 );
}
data[0] = (n >> 8) & 0xff;
data[1] = n & 0xff;
data[n0+2] = buflen+1;
data[n0+3] = type;
memcpy(data+n0+4, buffer, buflen );
if( hashed ) {
if( !realloced )
m_free(sig->hashed_data);
sig->hashed_data = data;
}
else {
if( !realloced )
m_free(sig->unhashed_data);
sig->unhashed_data = data;
}
}
/****************
* Put all the required stuff from SIG into subpackets of sig.
*/
void
build_sig_subpkt_from_sig( PKT_signature *sig )
{
u32 u;
byte buf[8];
u = sig->keyid[0];
buf[0] = (u >> 24) & 0xff;
buf[1] = (u >> 16) & 0xff;
buf[2] = (u >> 8) & 0xff;
buf[3] = u & 0xff;
u = sig->keyid[1];
buf[4] = (u >> 24) & 0xff;
buf[5] = (u >> 16) & 0xff;
buf[6] = (u >> 8) & 0xff;
buf[7] = u & 0xff;
build_sig_subpkt( sig, SIGSUBPKT_ISSUER, buf, 8 );
u = sig->timestamp;
buf[0] = (u >> 24) & 0xff;
buf[1] = (u >> 16) & 0xff;
buf[2] = (u >> 8) & 0xff;
buf[3] = u & 0xff;
build_sig_subpkt( sig, SIGSUBPKT_SIG_CREATED, buf, 4 );
}
static int
do_signature( IOBUF out, int ctb, PKT_signature *sig )
{
int rc = 0;
int n, i;
IOBUF a = iobuf_temp();
if( !sig->version )
iobuf_put( a, 3 );
else
iobuf_put( a, sig->version );
if( sig->version < 4 )
iobuf_put(a, 5 ); /* constant */
iobuf_put(a, sig->sig_class );
if( sig->version < 4 ) {
write_32(a, sig->timestamp );
write_32(a, sig->keyid[0] );
write_32(a, sig->keyid[1] );
}
iobuf_put(a, sig->pubkey_algo );
iobuf_put(a, sig->digest_algo );
if( sig->version >= 4 ) {
size_t n;
/* timestamp and keyid must have been packed into the
* subpackets prior to the call of this function, because
* these subpackets are hashed */
n = sig->hashed_data?((sig->hashed_data[0]<<8)
|sig->hashed_data[1]) :0;
write_16(a, n);
if( n )
iobuf_write( a, sig->hashed_data+2, n );
n = sig->unhashed_data?((sig->unhashed_data[0]<<8)
|sig->unhashed_data[1]) :0;
write_16(a, n);
if( n )
iobuf_write( a, sig->unhashed_data+2, n );
}
iobuf_put(a, sig->digest_start[0] );
iobuf_put(a, sig->digest_start[1] );
n = pubkey_get_nsig( sig->pubkey_algo );
if( !n )
write_fake_data( a, sig->data[0] );
for(i=0; i < n; i++ )
mpi_write(a, sig->data[i] );
if( is_RSA(sig->pubkey_algo) && sig->version < 4 )
write_sign_packet_header(out, ctb, iobuf_get_temp_length(a) );
else
write_header(out, ctb, iobuf_get_temp_length(a) );
if( iobuf_write_temp( out, a ) )
rc = G10ERR_WRITE_FILE;
iobuf_close(a);
return rc;
}
static int
do_onepass_sig( IOBUF out, int ctb, PKT_onepass_sig *ops )
{
int rc = 0;
IOBUF a = iobuf_temp();
write_version( a, ctb );
iobuf_put(a, ops->sig_class );
iobuf_put(a, ops->digest_algo );
iobuf_put(a, ops->pubkey_algo );
write_32(a, ops->keyid[0] );
write_32(a, ops->keyid[1] );
iobuf_put(a, ops->last );
write_header(out, ctb, iobuf_get_temp_length(a) );
if( iobuf_write_temp( out, a ) )
rc = G10ERR_WRITE_FILE;
iobuf_close(a);
return rc;
}
static int
write_16(IOBUF out, u16 a)
{
iobuf_put(out, a>>8);
if( iobuf_put(out,a) )
return -1;
return 0;
}
static int
write_32(IOBUF out, u32 a)
{
iobuf_put(out, a>> 24);
iobuf_put(out, a>> 16);
iobuf_put(out, a>> 8);
if( iobuf_put(out, a) )
return -1;
return 0;
}
/****************
* calculate the length of a header
*/
static int
calc_header_length( u32 len, int new_ctb )
{
if( !len )
return 1; /* only the ctb */
if( new_ctb ) {
if( len < 192 )
return 2;
if( len < 8384 )
return 3;
else
return 6;
}
if( len < 256 )
return 2;
if( len < 65536 )
return 3;
return 5;
}
/****************
* Write the CTB and the packet length
*/
static int
write_header( IOBUF out, int ctb, u32 len )
{
return write_header2( out, ctb, len, 0, 1 );
}
static int
write_sign_packet_header( IOBUF out, int ctb, u32 len )
{
/* work around a bug in the pgp read function for signature packets,
* which are not correctly coded and silently assume at some
* point 2 byte length headers.*/
iobuf_put(out, 0x89 );
iobuf_put(out, len >> 8 );
return iobuf_put(out, len ) == -1 ? -1:0;
}
/****************
* if HDRLEN is > 0, try to build a header of this length.
* we need this, so that we can hash packets without reading them again.
*/
static int
write_header2( IOBUF out, int ctb, u32 len, int hdrlen, int blkmode )
{
if( ctb & 0x40 )
return write_new_header( out, ctb, len, hdrlen );
if( hdrlen ) {
if( !len )
ctb |= 3;
else if( hdrlen == 2 && len < 256 )
;
else if( hdrlen == 3 && len < 65536 )
ctb |= 1;
else
ctb |= 2;
}
else {
if( !len )
ctb |= 3;
else if( len < 256 )
;
else if( len < 65536 )
ctb |= 1;
else
ctb |= 2;
}
if( iobuf_put(out, ctb ) )
return -1;
if( !len ) {
if( blkmode )
iobuf_set_block_mode(out, 8196 );
}
else {
if( ctb & 2 ) {
iobuf_put(out, len >> 24 );
iobuf_put(out, len >> 16 );
}
if( ctb & 3 )
iobuf_put(out, len >> 8 );
if( iobuf_put(out, len ) )
return -1;
}
return 0;
}
static int
write_new_header( IOBUF out, int ctb, u32 len, int hdrlen )
{
if( hdrlen )
log_bug("can't cope with hdrlen yet\n");
if( iobuf_put(out, ctb ) )
return -1;
if( !len ) {
iobuf_set_partial_block_mode(out, 512 );
}
else {
if( len < 192 ) {
if( iobuf_put(out, len ) )
return -1;
}
else if( len < 8384 ) {
len -= 192;
if( iobuf_put( out, (len / 256) + 192) )
return -1;
if( iobuf_put( out, (len % 256) ) )
return -1;
}
else {
if( iobuf_put( out, 0xff ) )
return -1;
if( iobuf_put( out, (len >> 24)&0xff ) )
return -1;
if( iobuf_put( out, (len >> 16)&0xff ) )
return -1;
if( iobuf_put( out, (len >> 8)&0xff ) )
return -1;
if( iobuf_put( out, len & 0xff ) )
return -1;
}
}
return 0;
}
static int
write_version( IOBUF out, int ctb )
{
if( iobuf_put( out, 3 ) )
return -1;
return 0;
}
diff --git a/g10/cipher.c b/g10/cipher.c
index 4664a4a83..c654db011 100644
--- a/g10/cipher.c
+++ b/g10/cipher.c
@@ -1,107 +1,107 @@
/* cipher.c - En-/De-ciphering filter
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "errors.h"
#include "iobuf.h"
#include "memory.h"
#include "util.h"
#include "filter.h"
#include "packet.h"
#include "options.h"
#define MIN_PARTIAL_SIZE 512
static void
write_header( cipher_filter_context_t *cfx, IOBUF a )
{
PACKET pkt;
PKT_encrypted ed;
byte temp[18];
unsigned blocksize;
memset( &ed, 0, sizeof ed );
ed.len = cfx->datalen;
ed.new_ctb = !ed.len && !opt.rfc1991;
init_packet( &pkt );
pkt.pkttype = PKT_ENCRYPTED;
pkt.pkt.encrypted = &ed;
if( build_packet( a, &pkt ))
log_bug("build_packet(ENCR_DATA) failed\n");
blocksize = cipher_get_blocksize( cfx->dek->algo );
if( blocksize < 8 || blocksize > 16 )
log_fatal("unsupported blocksize %u\n", blocksize );
randomize_buffer( temp, blocksize, 1 );
temp[blocksize] = temp[blocksize-2];
temp[blocksize+1] = temp[blocksize-1];
print_cipher_algo_note( cfx->dek->algo );
cfx->cipher_hd = cipher_open( cfx->dek->algo, CIPHER_MODE_AUTO_CFB, 1 );
cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen );
cipher_setiv( cfx->cipher_hd, NULL );
cipher_encrypt( cfx->cipher_hd, temp, temp, blocksize+2);
cipher_sync( cfx->cipher_hd );
iobuf_write(a, temp, blocksize+2);
cfx->header=1;
}
/****************
* This filter is used to en/de-cipher data with a conventional algorithm
*/
int
cipher_filter( void *opaque, int control,
IOBUF a, byte *buf, size_t *ret_len)
{
size_t size = *ret_len;
cipher_filter_context_t *cfx = opaque;
int rc=0;
if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */
rc = -1; /* not yet used */
}
else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
assert(a);
if( !cfx->header ) {
write_header( cfx, a );
}
cipher_encrypt( cfx->cipher_hd, buf, buf, size);
if( iobuf_write( a, buf, size ) )
rc = G10ERR_WRITE_FILE;
}
else if( control == IOBUFCTRL_FREE ) {
cipher_close(cfx->cipher_hd);
}
else if( control == IOBUFCTRL_DESC ) {
*(char**)buf = "cipher_filter";
}
return rc;
}
diff --git a/g10/comment.c b/g10/comment.c
index 71d524c40..6d27e481b 100644
--- a/g10/comment.c
+++ b/g10/comment.c
@@ -1,103 +1,103 @@
/* comment.c - write comment stuff
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "options.h"
#include "packet.h"
#include "errors.h"
#include "iobuf.h"
#include "memory.h"
#include "util.h"
#include "main.h"
#include "keydb.h"
int
write_comment( IOBUF out, const char *s )
{
PACKET pkt;
size_t n = strlen(s);
int rc=0;
pkt.pkttype = PKT_COMMENT;
if( *s != '#' ) {
pkt.pkt.comment = m_alloc( sizeof *pkt.pkt.comment + n );
pkt.pkt.comment->len = n+1;
*pkt.pkt.comment->data = '#';
strcpy(pkt.pkt.comment->data+1, s);
}
else {
pkt.pkt.comment = m_alloc( sizeof *pkt.pkt.comment + n - 1 );
pkt.pkt.comment->len = n;
strcpy(pkt.pkt.comment->data, s);
}
if( (rc = build_packet( out, &pkt )) )
log_error("build_packet(comment) failed: %s\n", g10_errstr(rc) );
free_packet( &pkt );
return rc;
}
KBNODE
make_comment_node( const char *s )
{
PACKET *pkt;
size_t n = strlen(s);
pkt = m_alloc_clear( sizeof *pkt );
pkt->pkttype = PKT_COMMENT;
pkt->pkt.comment = m_alloc( sizeof *pkt->pkt.comment + n - 1 );
pkt->pkt.comment->len = n;
strcpy(pkt->pkt.comment->data, s);
return new_kbnode( pkt );
}
KBNODE
make_mpi_comment_node( const char *s, MPI a )
{
PACKET *pkt;
byte *buf, *p, *pp;
unsigned n1, nb1;
size_t n = strlen(s);
nb1 = mpi_get_nbits( a );
p = buf = mpi_get_buffer( a, &n1, NULL );
pkt = m_alloc_clear( sizeof *pkt );
pkt->pkttype = PKT_COMMENT;
pkt->pkt.comment = m_alloc( sizeof *pkt->pkt.comment + n + 2 + n1 );
pkt->pkt.comment->len = n+1+2+n1;
pp = pkt->pkt.comment->data;
memcpy(pp, s, n+1);
pp[n+1] = nb1 >> 8;
pp[n+2] = nb1 ;
memcpy(pp+n+3, p, n1 );
m_free(buf);
return new_kbnode( pkt );
}
diff --git a/g10/compress.c b/g10/compress.c
index 6a2f8f8c5..31cc4c500 100644
--- a/g10/compress.c
+++ b/g10/compress.c
@@ -1,279 +1,279 @@
/* compress.c - compress filter
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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>
#include <assert.h>
#include <errno.h>
#include <zlib.h>
#include "util.h"
#include "memory.h"
#include "packet.h"
#include "filter.h"
#include "options.h"
static void
init_compress( compress_filter_context_t *zfx, z_stream *zs )
{
int rc;
int level;
if( opt.compress >= 0 && opt.compress <= 9 )
level = opt.compress;
else if( opt.compress == -1 )
level = Z_DEFAULT_COMPRESSION;
else if( opt.compress == 10 ) /* remove this ! */
level = 0;
else {
log_error("invalid compression level; using default level\n");
level = Z_DEFAULT_COMPRESSION;
}
if( (rc = zfx->algo == 1? deflateInit2( zs, level, Z_DEFLATED,
-13, 8, Z_DEFAULT_STRATEGY)
: deflateInit( zs, level )
) != Z_OK ) {
log_fatal("zlib problem: %s\n", zs->msg? zs->msg :
rc == Z_MEM_ERROR ? "out of core" :
rc == Z_VERSION_ERROR ? "invalid lib version" :
"unknown error" );
}
zfx->outbufsize = 8192;
zfx->outbuf = m_alloc( zfx->outbufsize );
}
static int
do_compress( compress_filter_context_t *zfx, z_stream *zs, int flush, IOBUF a )
{
int zrc;
unsigned n;
do {
zs->next_out = zfx->outbuf;
zs->avail_out = zfx->outbufsize;
if( DBG_FILTER )
log_debug("enter deflate: avail_in=%u, avail_out=%u, flush=%d\n",
(unsigned)zs->avail_in, (unsigned)zs->avail_out, flush );
zrc = deflate( zs, flush );
if( zrc == Z_STREAM_END && flush == Z_FINISH )
;
else if( zrc != Z_OK ) {
if( zs->msg )
log_fatal("zlib deflate problem: %s\n", zs->msg );
else
log_fatal("zlib deflate problem: rc=%d\n", zrc );
}
n = zfx->outbufsize - zs->avail_out;
if( DBG_FILTER )
log_debug("leave deflate: "
"avail_in=%u, avail_out=%u, n=%u, zrc=%d\n",
(unsigned)zs->avail_in, (unsigned)zs->avail_out,
(unsigned)n, zrc );
if( iobuf_write( a, zfx->outbuf, n ) ) {
log_debug("deflate: iobuf_write failed\n");
return G10ERR_WRITE_FILE;
}
} while( zs->avail_in || (flush == Z_FINISH && zrc != Z_STREAM_END) );
return 0;
}
static void
init_uncompress( compress_filter_context_t *zfx, z_stream *zs )
{
int rc;
/****************
* PGP uses a windowsize of 13 bits. Using a negative value for
* it forces zlib not to expect a zlib header. This is a
* undocumented feature Peter Gutmann told me about.
*/
if( (rc = zfx->algo == 1? inflateInit2( zs, -13)
: inflateInit( zs )) != Z_OK ) {
log_fatal("zlib problem: %s\n", zs->msg? zs->msg :
rc == Z_MEM_ERROR ? "out of core" :
rc == Z_VERSION_ERROR ? "invalid lib version" :
"unknown error" );
}
zfx->inbufsize = 2048;
zfx->inbuf = m_alloc( zfx->inbufsize );
zs->avail_in = 0;
}
static int
do_uncompress( compress_filter_context_t *zfx, z_stream *zs,
IOBUF a, size_t *ret_len )
{
int zrc;
int rc=0;
size_t n;
byte *p;
int c;
int refill = !zs->avail_in;
if( DBG_FILTER )
log_debug("begin inflate: avail_in=%u, avail_out=%u, inbuf=%u\n",
(unsigned)zs->avail_in, (unsigned)zs->avail_out,
(unsigned)zfx->inbufsize );
do {
if( zs->avail_in < zfx->inbufsize && refill ) {
n = zs->avail_in;
if( !n )
zs->next_in = zfx->inbuf;
for( p=zfx->inbuf+n; n < zfx->inbufsize; n++, p++ ) {
if( (c=iobuf_get(a)) == -1 )
break;
*p = c & 0xff;
}
zs->avail_in = n;
}
refill = 1;
if( DBG_FILTER )
log_debug("enter inflate: avail_in=%u, avail_out=%u\n",
(unsigned)zs->avail_in, (unsigned)zs->avail_out);
#ifdef Z_SYNC_FLUSH
zrc = inflate( zs, Z_SYNC_FLUSH );
#else
zrc = inflate( zs, Z_PARTIAL_FLUSH );
#endif
if( DBG_FILTER )
log_debug("leave inflate: avail_in=%u, avail_out=%u, zrc=%d\n",
(unsigned)zs->avail_in, (unsigned)zs->avail_out, zrc);
if( zrc == Z_STREAM_END )
rc = -1; /* eof */
else if( zrc != Z_OK && zrc != Z_BUF_ERROR ) {
if( zs->msg )
log_fatal("zlib inflate problem: %s\n", zs->msg );
else
log_fatal("zlib inflate problem: rc=%d\n", zrc );
}
} while( zs->avail_out && zrc != Z_STREAM_END && zrc != Z_BUF_ERROR );
*ret_len = zfx->outbufsize - zs->avail_out;
if( DBG_FILTER )
log_debug("do_uncompress: returning %u bytes\n", (unsigned)*ret_len );
return rc;
}
int
compress_filter( void *opaque, int control,
IOBUF a, byte *buf, size_t *ret_len)
{
size_t size = *ret_len;
compress_filter_context_t *zfx = opaque;
z_stream *zs = zfx->opaque;
int rc=0;
if( control == IOBUFCTRL_UNDERFLOW ) {
if( !zfx->status ) {
zs = zfx->opaque = m_alloc_clear( sizeof *zs );
init_uncompress( zfx, zs );
zfx->status = 1;
}
zs->next_out = buf;
zs->avail_out = size;
zfx->outbufsize = size; /* needed only for calculation */
rc = do_uncompress( zfx, zs, a, ret_len );
}
else if( control == IOBUFCTRL_FLUSH ) {
if( !zfx->status ) {
PACKET pkt;
PKT_compressed cd;
if( !zfx->algo )
zfx->algo = opt.def_compress_algo;
memset( &cd, 0, sizeof cd );
cd.len = 0;
cd.algorithm = zfx->algo;
init_packet( &pkt );
pkt.pkttype = PKT_COMPRESSED;
pkt.pkt.compressed = &cd;
if( build_packet( a, &pkt ))
log_bug("build_packet(PKT_COMPRESSED) failed\n");
zs = zfx->opaque = m_alloc_clear( sizeof *zs );
init_compress( zfx, zs );
zfx->status = 2;
}
zs->next_in = buf;
zs->avail_in = size;
rc = do_compress( zfx, zs, Z_NO_FLUSH, a );
}
else if( control == IOBUFCTRL_FREE ) {
if( zfx->status == 1 ) {
inflateEnd(zs);
m_free(zs);
zfx->opaque = NULL;
m_free(zfx->outbuf); zfx->outbuf = NULL;
}
else if( zfx->status == 2 ) {
zs->next_in = buf;
zs->avail_in = 0;
do_compress( zfx, zs, Z_FINISH, a );
deflateEnd(zs);
m_free(zs);
zfx->opaque = NULL;
m_free(zfx->outbuf); zfx->outbuf = NULL;
}
}
else if( control == IOBUFCTRL_DESC )
*(char**)buf = "compress_filter";
return rc;
}
/****************
* Handle a compressed packet
*/
int
handle_compressed( PKT_compressed *cd,
int (*callback)(IOBUF, void *), void *passthru )
{
compress_filter_context_t cfx;
int rc;
memset( &cfx, 0, sizeof cfx );
if( cd->algorithm < 1 || cd->algorithm > 2 )
return G10ERR_COMPR_ALGO;
cfx.algo = cd->algorithm;
iobuf_push_filter( cd->buf, compress_filter, &cfx );
if( callback )
rc = callback(cd->buf, passthru );
else
rc = proc_packets(cd->buf);
iobuf_pop_filter( cd->buf, compress_filter, &cfx );
#if 0
if( cd->len )
iobuf_set_limit( cd->buf, 0 ); /* disable the readlimit */
else
iobuf_clear_eof( cd->buf );
#endif
cd->buf = NULL;
return rc;
}
diff --git a/g10/dearmor.c b/g10/dearmor.c
index 6b15f491b..43fc6b059 100644
--- a/g10/dearmor.c
+++ b/g10/dearmor.c
@@ -1,122 +1,122 @@
/* dearmor.c - Armor utility
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "errors.h"
#include "iobuf.h"
#include "memory.h"
#include "util.h"
#include "filter.h"
#include "packet.h"
#include "options.h"
#include "main.h"
/****************
* Take an armor file and write it out without armor
*/
int
dearmor_file( const char *fname )
{
armor_filter_context_t afx;
IOBUF inp = NULL, out = NULL;
int rc = 0;
int c;
memset( &afx, 0, sizeof afx);
/* prepare iobufs */
if( !(inp = iobuf_open(fname)) ) {
log_error("can't open %s: %s\n", fname? fname: "[stdin]",
strerror(errno) );
rc = G10ERR_OPEN_FILE;
goto leave;
}
iobuf_push_filter( inp, armor_filter, &afx );
if( (rc = open_outfile( fname, 0, &out )) )
goto leave;
while( (c = iobuf_get(inp)) != -1 )
iobuf_put( out, c );
leave:
if( rc )
iobuf_cancel(out);
else
iobuf_close(out);
iobuf_close(inp);
return rc;
}
/****************
* Take file and write it out with armor
*/
int
enarmor_file( const char *fname )
{
armor_filter_context_t afx;
IOBUF inp = NULL, out = NULL;
int rc = 0;
int c;
memset( &afx, 0, sizeof afx);
/* prepare iobufs */
if( !(inp = iobuf_open(fname)) ) {
log_error("can't open %s: %s\n", fname? fname: "[stdin]",
strerror(errno) );
rc = G10ERR_OPEN_FILE;
goto leave;
}
if( (rc = open_outfile( fname, 1, &out )) )
goto leave;
afx.what = 4;
afx.hdrlines = "Comment: Use \"gpgm --dearmor\" for unpacking\n";
iobuf_push_filter( out, armor_filter, &afx );
while( (c = iobuf_get(inp)) != -1 )
iobuf_put( out, c );
leave:
if( rc )
iobuf_cancel(out);
else
iobuf_close(out);
iobuf_close(inp);
return rc;
}
diff --git a/g10/decrypt.c b/g10/decrypt.c
index cb1cccd4c..4094321c3 100644
--- a/g10/decrypt.c
+++ b/g10/decrypt.c
@@ -1,82 +1,82 @@
/* verify.c - verify signed data
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "options.h"
#include "packet.h"
#include "errors.h"
#include "iobuf.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "main.h"
#include "i18n.h"
/****************
* Assume that the input is an encrypted message and decrypt
* (and if signed, verify the signature on) it.
* This command differs from the default operation, as it never
* writes to the filename which is included in the file and it
* rejects files which don't begin with an encrypted message.
*/
int
decrypt_message( const char *filename )
{
IOBUF fp;
armor_filter_context_t afx;
int rc;
int no_out=0;
/* open the message file */
fp = iobuf_open(filename);
if( !fp ) {
log_error(_("can't open '%s'\n"), print_fname_stdin(filename));
return G10ERR_OPEN_FILE;
}
if( !opt.no_armor ) {
if( use_armor_filter( fp ) ) {
memset( &afx, 0, sizeof afx);
iobuf_push_filter( fp, armor_filter, &afx );
}
}
if( !opt.outfile ) {
no_out = 1;
opt.outfile = "-";
}
rc = proc_encryption_packets( fp );
if( no_out )
opt.outfile = NULL;
iobuf_close(fp);
return rc;
}
diff --git a/g10/delkey.c b/g10/delkey.c
index 08648b84b..8d4f1a5b0 100644
--- a/g10/delkey.c
+++ b/g10/delkey.c
@@ -1,160 +1,160 @@
/* delkey.c - delete keys
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <ctype.h>
#include "options.h"
#include "packet.h"
#include "errors.h"
#include "iobuf.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "main.h"
#include "trustdb.h"
#include "filter.h"
#include "ttyio.h"
#include "status.h"
#include "i18n.h"
/****************
* Delete a public or secret key from a keyring.
*/
int
delete_key( const char *username, int secret )
{
int rc = 0;
KBNODE keyblock = NULL;
KBNODE node;
KBPOS kbpos;
PKT_public_key *pk = NULL;
PKT_secret_key *sk = NULL;
u32 keyid[2];
int okay=0;
int yes;
/* search the userid */
rc = secret? find_secret_keyblock_byname( &kbpos, username )
: find_keyblock_byname( &kbpos, username );
if( rc ) {
log_error(_("%s: user not found\n"), username );
goto leave;
}
/* read the keyblock */
rc = read_keyblock( &kbpos, &keyblock );
if( rc ) {
log_error("%s: read problem: %s\n", username, g10_errstr(rc) );
goto leave;
}
/* get the keyid from the keyblock */
node = find_kbnode( keyblock, secret? PKT_SECRET_KEY:PKT_PUBLIC_KEY );
if( !node ) {
log_error("Oops; key not found anymore!\n");
rc = G10ERR_GENERAL;
goto leave;
}
if( secret ) {
sk = node->pkt->pkt.secret_key;
keyid_from_sk( sk, keyid );
}
else {
pk = node->pkt->pkt.public_key;
keyid_from_pk( pk, keyid );
rc = seckey_available( keyid );
if( !rc ) {
log_error(_(
"there is a secret key for this public key!\n"));
log_info(_(
"use option \"--delete-secret-key\" to delete it first.\n"));
rc = -1;
}
else if( rc != G10ERR_NO_SECKEY )
log_error("%s: get secret key: %s\n", username, g10_errstr(rc) );
else
rc = 0;
}
if( rc )
rc = 0;
else if( opt.batch && secret )
log_error(_("can't do that in batchmode\n"));
else if( opt.batch && opt.answer_yes )
okay++;
else if( opt.batch )
log_error(_("can't do that in batchmode without \"--yes\"\n"));
else {
char *p;
size_t n;
if( secret )
tty_printf("sec %4u%c/%08lX %s ",
nbits_from_sk( sk ),
pubkey_letter( sk->pubkey_algo ),
keyid[1], datestr_from_sk(sk) );
else
tty_printf("pub %4u%c/%08lX %s ",
nbits_from_pk( pk ),
pubkey_letter( pk->pubkey_algo ),
keyid[1], datestr_from_pk(pk) );
p = get_user_id( keyid, &n );
tty_print_string( p, n );
m_free(p);
tty_printf("\n\n");
yes = cpr_get_answer_is_yes( secret? "delete_key.secret.okay"
: "delete_key.okay",
_("Delete this key from the keyring? "));
if( !cpr_enabled() && secret && yes ) {
/* I think it is not required to check a passphrase; if
* the user is so stupid as to let others access his secret keyring
* (and has no backup) - it is up him to read some very
* basic texts about security.
*/
yes = cpr_get_answer_is_yes("delete_key.secret.okay",
_("This is a secret key! - really delete? "));
}
if( yes )
okay++;
}
if( okay ) {
rc = delete_keyblock( &kbpos );
if( rc ) {
log_error("delete_keyblock failed: %s\n", g10_errstr(rc) );
goto leave;
}
}
leave:
release_kbnode( keyblock );
return rc;
}
diff --git a/g10/encode.c b/g10/encode.c
index 8245dd02e..303cf798a 100644
--- a/g10/encode.c
+++ b/g10/encode.c
@@ -1,416 +1,416 @@
/* encode.c - encode data
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "options.h"
#include "packet.h"
#include "errors.h"
#include "iobuf.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "main.h"
#include "filter.h"
#include "trustdb.h"
#include "i18n.h"
static int encode_simple( const char *filename, int mode );
static int write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out );
/****************
* Encode FILENAME with only the symmetric cipher. Take input from
* stdin if FILENAME is NULL.
*/
int
encode_symmetric( const char *filename )
{
return encode_simple( filename, 1 );
}
/****************
* Encode FILENAME as a literal data packet only. Take input from
* stdin if FILENAME is NULL.
*/
int
encode_store( const char *filename )
{
return encode_simple( filename, 0 );
}
static int
encode_simple( const char *filename, int mode )
{
IOBUF inp, out;
PACKET pkt;
PKT_plaintext *pt;
STRING2KEY *s2k = NULL;
int rc = 0;
u32 filesize;
cipher_filter_context_t cfx;
armor_filter_context_t afx;
compress_filter_context_t zfx;
int do_compress = opt.compress && !opt.rfc1991;
memset( &cfx, 0, sizeof cfx);
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx);
init_packet(&pkt);
/* prepare iobufs */
if( !(inp = iobuf_open(filename)) ) {
log_error(_("%s: can't open: %s\n"), filename? filename: "[stdin]",
strerror(errno) );
return G10ERR_OPEN_FILE;
}
cfx.dek = NULL;
if( mode ) {
s2k = m_alloc_clear( sizeof *s2k );
s2k->mode = opt.rfc1991? 0:opt.s2k_mode;
s2k->hash_algo = opt.def_digest_algo ? opt.def_digest_algo
: opt.s2k_digest_algo;
cfx.dek = passphrase_to_dek( NULL,
opt.def_cipher_algo ? opt.def_cipher_algo
: opt.s2k_cipher_algo , s2k, 2 );
if( !cfx.dek || !cfx.dek->keylen ) {
rc = G10ERR_PASSPHRASE;
m_free(cfx.dek);
m_free(s2k);
iobuf_close(inp);
log_error(_("error creating passphrase: %s\n"), g10_errstr(rc) );
return rc;
}
}
if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) ) {
iobuf_close(inp);
m_free(cfx.dek);
m_free(s2k);
return rc;
}
if( opt.armor )
iobuf_push_filter( out, armor_filter, &afx );
#ifdef ENABLE_COMMENT_PACKETS
else {
write_comment( out, "#created by GNUPG v" VERSION " ("
PRINTABLE_OS_NAME ")");
if( opt.comment_string )
write_comment( out, opt.comment_string );
}
#endif
if( s2k && !opt.rfc1991 ) {
PKT_symkey_enc *enc = m_alloc_clear( sizeof *enc );
enc->version = 4;
enc->cipher_algo = cfx.dek->algo;
enc->s2k = *s2k;
pkt.pkttype = PKT_SYMKEY_ENC;
pkt.pkt.symkey_enc = enc;
if( (rc = build_packet( out, &pkt )) )
log_error("build symkey packet failed: %s\n", g10_errstr(rc) );
m_free(enc);
}
/* setup the inner packet */
if( filename || opt.set_filename ) {
char *s = make_basename( opt.set_filename ? opt.set_filename : filename );
pt = m_alloc( sizeof *pt + strlen(s) - 1 );
pt->namelen = strlen(s);
memcpy(pt->name, s, pt->namelen );
m_free(s);
}
else { /* no filename */
pt = m_alloc( sizeof *pt - 1 );
pt->namelen = 0;
}
if( filename ) {
if( !(filesize = iobuf_get_filelength(inp)) )
log_info(_("%s: WARNING: empty file\n"), filename );
}
else
filesize = 0; /* stdin */
pt->timestamp = make_timestamp();
pt->mode = 'b';
pt->len = filesize;
pt->buf = inp;
pkt.pkttype = PKT_PLAINTEXT;
pkt.pkt.plaintext = pt;
cfx.datalen = filesize && !do_compress ? calc_packet_length( &pkt ) : 0;
/* register the cipher filter */
if( mode )
iobuf_push_filter( out, cipher_filter, &cfx );
/* register the compress filter */
if( do_compress )
iobuf_push_filter( out, compress_filter, &zfx );
/* do the work */
if( (rc = build_packet( out, &pkt )) )
log_error("build_packet failed: %s\n", g10_errstr(rc) );
/* finish the stuff */
iobuf_close(inp);
iobuf_close(out); /* fixme: check returncode */
pt->buf = NULL;
free_packet(&pkt);
m_free(cfx.dek);
m_free(s2k);
return rc;
}
/****************
* Encrypt the file with the given userids (or ask if none
* is supplied).
*/
int
encode_crypt( const char *filename, STRLIST remusr )
{
IOBUF inp = NULL, out = NULL;
PACKET pkt;
PKT_plaintext *pt = NULL;
int rc = 0;
u32 filesize;
cipher_filter_context_t cfx;
armor_filter_context_t afx;
compress_filter_context_t zfx;
PK_LIST pk_list;
int do_compress = opt.compress && !opt.rfc1991;
memset( &cfx, 0, sizeof cfx);
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx);
init_packet(&pkt);
if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC)) )
return rc;
/* prepare iobufs */
if( !(inp = iobuf_open(filename)) ) {
log_error(_("can't open %s: %s\n"), filename? filename: "[stdin]",
strerror(errno) );
rc = G10ERR_OPEN_FILE;
goto leave;
}
else if( opt.verbose )
log_info(_("reading from '%s'\n"), filename? filename: "[stdin]");
if( (rc = open_outfile( filename, opt.armor? 1:0, &out )) )
goto leave;
if( opt.armor )
iobuf_push_filter( out, armor_filter, &afx );
#ifdef ENABLE_COMMENT_PACKETS
else {
write_comment( out, "#created by GNUPG v" VERSION " ("
PRINTABLE_OS_NAME ")");
if( opt.comment_string )
write_comment( out, opt.comment_string );
}
#endif
/* create a session key */
cfx.dek = m_alloc_secure( sizeof *cfx.dek );
if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
cfx.dek->algo = select_algo_from_prefs( pk_list, PREFTYPE_SYM );
if( cfx.dek->algo == -1 )
cfx.dek->algo = DEFAULT_CIPHER_ALGO;
}
else
cfx.dek->algo = opt.def_cipher_algo;
make_session_key( cfx.dek );
if( DBG_CIPHER )
log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen );
rc = write_pubkey_enc_from_list( pk_list, cfx.dek, out );
if( rc )
goto leave;
/* setup the inner packet */
if( filename || opt.set_filename ) {
char *s = make_basename( opt.set_filename ? opt.set_filename : filename );
pt = m_alloc( sizeof *pt + strlen(s) - 1 );
pt->namelen = strlen(s);
memcpy(pt->name, s, pt->namelen );
m_free(s);
}
else { /* no filename */
pt = m_alloc( sizeof *pt - 1 );
pt->namelen = 0;
}
if( filename ) {
if( !(filesize = iobuf_get_filelength(inp)) )
log_info(_("%s: WARNING: empty file\n"), filename );
}
else
filesize = 0; /* stdin */
pt->timestamp = make_timestamp();
pt->mode = 'b';
pt->len = filesize;
pt->new_ctb = !pt->len && !opt.rfc1991;
pt->buf = inp;
pkt.pkttype = PKT_PLAINTEXT;
pkt.pkt.plaintext = pt;
cfx.datalen = filesize && !do_compress? calc_packet_length( &pkt ) : 0;
/* register the cipher filter */
iobuf_push_filter( out, cipher_filter, &cfx );
/* register the compress filter */
if( do_compress ) {
int compr_algo = select_algo_from_prefs( pk_list, PREFTYPE_COMPR );
if( !compr_algo )
; /* don't use compression */
else {
if( compr_algo == 1 )
zfx.algo = 1; /* default is 2 */
iobuf_push_filter( out, compress_filter, &zfx );
}
}
/* do the work */
if( (rc = build_packet( out, &pkt )) )
log_error("build_packet failed: %s\n", g10_errstr(rc) );
/* finish the stuff */
leave:
iobuf_close(inp);
if( rc )
iobuf_cancel(out);
else
iobuf_close(out); /* fixme: check returncode */
if( pt )
pt->buf = NULL;
free_packet(&pkt);
m_free(cfx.dek);
release_pk_list( pk_list );
return rc;
}
/****************
* Filter to do a complete public key encryption.
*/
int
encrypt_filter( void *opaque, int control,
IOBUF a, byte *buf, size_t *ret_len)
{
size_t size = *ret_len;
encrypt_filter_context_t *efx = opaque;
int rc=0;
if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */
BUG(); /* not used */
}
else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
if( !efx->header_okay ) {
efx->cfx.dek = m_alloc_secure( sizeof *efx->cfx.dek );
if( !opt.def_cipher_algo ) { /* try to get it from the prefs */
efx->cfx.dek->algo =
select_algo_from_prefs( efx->pk_list, PREFTYPE_SYM );
if( efx->cfx.dek->algo == -1 )
efx->cfx.dek->algo = DEFAULT_CIPHER_ALGO;
}
else
efx->cfx.dek->algo = opt.def_cipher_algo;
make_session_key( efx->cfx.dek );
if( DBG_CIPHER )
log_hexdump("DEK is: ",
efx->cfx.dek->key, efx->cfx.dek->keylen );
rc = write_pubkey_enc_from_list( efx->pk_list, efx->cfx.dek, a );
if( rc )
return rc;
iobuf_push_filter( a, cipher_filter, &efx->cfx );
efx->header_okay = 1;
}
rc = iobuf_write( a, buf, size );
}
else if( control == IOBUFCTRL_FREE ) {
}
else if( control == IOBUFCTRL_DESC ) {
*(char**)buf = "encrypt_filter";
}
return rc;
}
/****************
* Write pubkey-enc packets from the list of PKs to OUT.
*/
static int
write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
{
PACKET pkt;
PKT_public_key *pk;
PKT_pubkey_enc *enc;
int rc;
for( ; pk_list; pk_list = pk_list->next ) {
MPI frame;
pk = pk_list->pk;
print_pubkey_algo_note( pk->pubkey_algo );
enc = m_alloc_clear( sizeof *enc );
enc->pubkey_algo = pk->pubkey_algo;
keyid_from_pk( pk, enc->keyid );
enc->throw_keyid = opt.throw_keyid;
frame = encode_session_key( dek, pubkey_nbits( pk->pubkey_algo,
pk->pkey ) );
rc = pubkey_encrypt( pk->pubkey_algo, enc->data, frame, pk->pkey );
mpi_free( frame );
if( rc )
log_error("pubkey_encrypt failed: %s\n", g10_errstr(rc) );
else {
if( opt.verbose ) {
char *ustr = get_user_id_string( enc->keyid );
log_info(_("%s/%s encrypted for: %s\n"),
pubkey_algo_to_string(enc->pubkey_algo),
cipher_algo_to_string(dek->algo), ustr );
m_free(ustr);
}
/* and write it */
init_packet(&pkt);
pkt.pkttype = PKT_PUBKEY_ENC;
pkt.pkt.pubkey_enc = enc;
rc = build_packet( out, &pkt );
if( rc )
log_error("build_packet(pubkey_enc) failed: %s\n", g10_errstr(rc));
}
free_pubkey_enc(enc);
if( rc )
return rc;
}
return 0;
}
diff --git a/g10/encr-data.c b/g10/encr-data.c
index e5338c75d..ff7954c64 100644
--- a/g10/encr-data.c
+++ b/g10/encr-data.c
@@ -1,141 +1,141 @@
/* encr-data.c - process an encrypted data packet
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "packet.h"
#include "mpi.h"
#include "cipher.h"
#include "options.h"
#include "i18n.h"
static int decode_filter( void *opaque, int control, IOBUF a,
byte *buf, size_t *ret_len);
typedef struct {
CIPHER_HANDLE cipher_hd;
} decode_filter_ctx_t;
/****************
* Decrypt the data, specified by ED with the key DEK.
*/
int
decrypt_data( PKT_encrypted *ed, DEK *dek )
{
decode_filter_ctx_t dfx;
byte *p;
int rc, c, i;
byte temp[32];
unsigned blocksize;
if( opt.verbose ) {
const char *s = cipher_algo_to_string( dek->algo );
if( s )
log_info(_("%s encrypted data\n"), s );
else
log_info(_("encrypted with unknown algorithm %d\n"), dek->algo );
}
if( (rc=check_cipher_algo(dek->algo)) )
return rc;
blocksize = cipher_get_blocksize(dek->algo);
if( !blocksize || blocksize > 16 )
log_fatal("unsupported blocksize %u\n", blocksize );
if( ed->len && ed->len < (blocksize+2) )
log_bug("Nanu\n"); /* oops: found a bug */
dfx.cipher_hd = cipher_open( dek->algo, CIPHER_MODE_AUTO_CFB, 1 );
rc = cipher_setkey( dfx.cipher_hd, dek->key, dek->keylen );
if( rc == G10ERR_WEAK_KEY )
log_info(_("WARNING: Message was encrypted with "
"a weak key in the symmetric cipher.\n"));
else if( rc )
log_error("key setup failed: %s\n", g10_errstr(rc) );
cipher_setiv( dfx.cipher_hd, NULL );
if( ed->len ) {
iobuf_set_limit( ed->buf, ed->len );
for(i=0; i < (blocksize+2) && ed->len; i++, ed->len-- )
temp[i] = iobuf_get(ed->buf);
}
else {
for(i=0; i < (blocksize+2); i++ )
if( (c=iobuf_get(ed->buf)) == -1 )
break;
else
temp[i] = c;
}
cipher_decrypt( dfx.cipher_hd, temp, temp, blocksize+2);
cipher_sync( dfx.cipher_hd );
p = temp;
if( p[blocksize-2] != p[blocksize] || p[blocksize-1] != p[blocksize+1] ) {
cipher_close(dfx.cipher_hd);
return G10ERR_BAD_KEY;
}
iobuf_push_filter( ed->buf, decode_filter, &dfx );
proc_packets(ed->buf);
iobuf_pop_filter( ed->buf, decode_filter, &dfx );
if( ed->len )
iobuf_set_limit( ed->buf, 0 ); /* disable the readlimit */
else
iobuf_clear_eof( ed->buf );
ed->buf = NULL;
cipher_close(dfx.cipher_hd);
return 0;
}
static int
decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
{
decode_filter_ctx_t *fc = opaque;
size_t n, size = *ret_len;
int rc = 0;
int c;
if( control == IOBUFCTRL_UNDERFLOW ) {
assert(a);
for(n=0; n < size; n++ ) {
if( (c = iobuf_get(a)) == -1 )
break;
buf[n] = c;
}
if( n )
cipher_decrypt( fc->cipher_hd, buf, buf, n);
else
rc = -1; /* eof */
*ret_len = n;
}
else if( control == IOBUFCTRL_DESC ) {
*(char**)buf = "decode_filter";
}
return rc;
}
diff --git a/g10/export.c b/g10/export.c
index c9056115d..6b4b41cdd 100644
--- a/g10/export.c
+++ b/g10/export.c
@@ -1,178 +1,178 @@
/* export.c
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "options.h"
#include "packet.h"
#include "errors.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "main.h"
#include "i18n.h"
static int do_export( STRLIST users, int secret, int onlyrfc );
/****************
* Export the public keys (to standard out or --output).
* Depending on opt.armor the output is armored.
* If onlyrfc is True only RFC24404 compatible keys are exported.
* If USERS is NULL, the complete ring will be exported.
*/
int
export_pubkeys( STRLIST users, int onlyrfc )
{
return do_export( users, 0, onlyrfc );
}
int
export_seckeys( STRLIST users )
{
return do_export( users, 1, 0 );
}
static int
do_export( STRLIST users, int secret, int onlyrfc )
{
int rc = 0;
armor_filter_context_t afx;
compress_filter_context_t zfx;
IOBUF out = NULL;
PACKET pkt;
KBNODE keyblock = NULL;
KBNODE kbctx, node;
KBPOS kbpos;
STRLIST sl;
int all = !users;
int any=0;
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx);
init_packet( &pkt );
if( (rc = open_outfile( NULL, 0, &out )) )
goto leave;
if( opt.armor ) {
afx.what = secret?5:1;
iobuf_push_filter( out, armor_filter, &afx );
}
if( opt.compress_keys && opt.compress )
iobuf_push_filter( out, compress_filter, &zfx );
if( all ) {
rc = enum_keyblocks( secret?5:0, &kbpos, &keyblock );
if( rc ) {
if( rc != -1 )
log_error("enum_keyblocks(open) failed: %s\n", g10_errstr(rc) );
goto leave;
}
all = 2;
}
/* use the correct sequence. strlist_last,prev do work correctly with
* NULL pointers :-) */
for( sl=strlist_last(users); sl || all ; sl=strlist_prev( users, sl )) {
if( all ) { /* get the next user */
rc = enum_keyblocks( 1, &kbpos, &keyblock );
if( rc == -1 ) /* EOF */
break;
if( rc ) {
log_error("enum_keyblocks(read) failed: %s\n", g10_errstr(rc));
break;
}
}
else {
/* search the userid */
rc = secret? find_secret_keyblock_byname( &kbpos, sl->d )
: find_keyblock_byname( &kbpos, sl->d );
if( rc ) {
log_error(_("%s: user not found: %s\n"), sl->d, g10_errstr(rc));
rc = 0;
continue;
}
/* read the keyblock */
rc = read_keyblock( &kbpos, &keyblock );
}
if( rc ) {
log_error(_("certificate read problem: %s\n"), g10_errstr(rc));
goto leave;
}
/* do not export keys which are incompatible with rfc2440 */
if( onlyrfc && (node = find_kbnode( keyblock, PKT_PUBLIC_KEY )) ) {
PKT_public_key *pk = node->pkt->pkt.public_key;
if( pk->version == 3 && pk->pubkey_algo > 3 ) {
log_info(_("key %08lX: not a rfc2440 key - skipped\n"),
(ulong)keyid_from_pk( pk, NULL) );
continue;
}
}
/* and write it */
for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) {
/* don't export any comment packets but those in the
* secret keyring */
if( !secret && node->pkt->pkttype == PKT_COMMENT )
continue;
/* do not export packets which are marked as not exportable */
if( node->pkt->pkttype == PKT_SIGNATURE ) {
const char *p;
p = parse_sig_subpkt2( node->pkt->pkt.signature,
SIGSUBPKT_EXPORTABLE, NULL );
if( p && !*p )
continue; /* not exportable */
}
if( (rc = build_packet( out, node->pkt )) ) {
log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, g10_errstr(rc) );
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
any++;
}
if( rc == -1 )
rc = 0;
leave:
if( all == 2 )
enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
release_kbnode( keyblock );
if( rc || !any )
iobuf_cancel(out);
else
iobuf_close(out);
if( !any )
log_info(_("WARNING: nothing exported\n"));
return rc;
}
diff --git a/g10/filter.h b/g10/filter.h
index f4d924965..75d629e68 100644
--- a/g10/filter.h
+++ b/g10/filter.h
@@ -1,105 +1,105 @@
/* filter.h
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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_FILTER_H
#define G10_FILTER_H
#include "types.h"
#include "cipher.h"
typedef struct {
MD_HANDLE md; /* catch all */
size_t maxbuf_size;
} md_filter_context_t;
typedef struct {
int status;
int what;
int only_keyblocks; /* skip all headers but ".... key block" */
byte radbuf[4];
int idx, idx2;
u32 crc;
byte helpbuf[100];
int helpidx, helplen;
unsigned empty; /* empty line counter */
int hashes; /* detected hash algorithms */
int faked;
int parse_state;
int inp_checked; /* set if inp has been checked */
int inp_bypass; /* set if the input is not armored */
int any_data;
const char *hdrlines;
int not_dash_escaped;
} armor_filter_context_t;
typedef struct {
int status;
void *opaque; /* (used for z_stream) */
byte *inbuf;
unsigned inbufsize;
byte *outbuf;
unsigned outbufsize;
int algo; /* compress algo */
} compress_filter_context_t;
typedef struct {
DEK *dek;
u32 datalen;
CIPHER_HANDLE cipher_hd;
int header;
} cipher_filter_context_t;
typedef struct {
int eof;
size_t idx;
size_t len;
byte buf[256];
} text_filter_context_t;
/* encrypt_filter_context_t defined in main.h */
/*-- mdfilter.c --*/
int md_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len);
void free_md_filter_context( md_filter_context_t *mfx );
/*-- armor.c --*/
int use_armor_filter( IOBUF a );
int armor_filter( void *opaque, int control,
IOBUF chain, byte *buf, size_t *ret_len);
/*-- compress.c --*/
int compress_filter( void *opaque, int control,
IOBUF chain, byte *buf, size_t *ret_len);
/*-- cipher.c --*/
int cipher_filter( void *opaque, int control,
IOBUF chain, byte *buf, size_t *ret_len);
/*-- textfilter.c --*/
int text_filter( void *opaque, int control,
IOBUF chain, byte *buf, size_t *ret_len);
#endif /*G10_FILTER_H*/
diff --git a/g10/free-packet.c b/g10/free-packet.c
index e2bbc1640..bd4ed0422 100644
--- a/g10/free-packet.c
+++ b/g10/free-packet.c
@@ -1,460 +1,460 @@
/* free-packet.c - cleanup stuff for packets
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "packet.h"
#include "iobuf.h"
#include "mpi.h"
#include "util.h"
#include "cipher.h"
#include "memory.h"
#include "options.h"
void
free_symkey_enc( PKT_symkey_enc *enc )
{
m_free(enc);
}
void
free_pubkey_enc( PKT_pubkey_enc *enc )
{
int n, i;
n = pubkey_get_nenc( enc->pubkey_algo );
if( !n ) {
m_free(enc->data[0]);
enc->data[0] = NULL;
}
for(i=0; i < n; i++ )
mpi_free( enc->data[i] );
m_free(enc);
}
void
free_seckey_enc( PKT_signature *sig )
{
int n, i;
n = pubkey_get_nsig( sig->pubkey_algo );
if( !n ) {
m_free(sig->data[0]);
sig->data[0] = NULL;
}
for(i=0; i < n; i++ )
mpi_free( sig->data[i] );
m_free(sig->hashed_data);
m_free(sig->unhashed_data);
m_free(sig);
}
void
release_public_key_parts( PKT_public_key *pk )
{
int n, i;
n = pubkey_get_npkey( pk->pubkey_algo );
if( !n ) {
m_free(pk->pkey[0]);
pk->pkey[0] = NULL;
}
for(i=0; i < n; i++ ) {
mpi_free( pk->pkey[i] );
pk->pkey[i] = NULL;
}
if( pk->namehash ) {
m_free(pk->namehash);
pk->namehash = NULL;
}
}
void
free_public_key( PKT_public_key *pk )
{
release_public_key_parts( pk );
m_free(pk);
}
static void *
cp_fake_data( MPI a )
{
byte *d, *s;
u16 len;
if( !a )
return NULL;
s = (byte*)a;
len = (s[0] << 8) | s[1];
d = m_alloc( len+2 );
memcpy(d, s, len+2);
return d;
}
static void *
cp_data_block( byte *s )
{
byte *d;
u16 len;
if( !s )
return NULL;
len = (s[0] << 8) | s[1];
d = m_alloc( len+2 );
memcpy(d, s, len+2);
return d;
}
PKT_public_key *
copy_public_key_new_namehash( PKT_public_key *d, PKT_public_key *s,
const byte *namehash )
{
int n, i;
if( !d )
d = m_alloc(sizeof *d);
memcpy( d, s, sizeof *d );
if( namehash ) {
d->namehash = m_alloc( 20 );
memcpy(d->namehash, namehash, 20 );
}
else if( s->namehash ) {
d->namehash = m_alloc( 20 );
memcpy(d->namehash, s->namehash, 20 );
}
n = pubkey_get_npkey( s->pubkey_algo );
if( !n )
d->pkey[0] = cp_fake_data(s->pkey[0]);
else {
for(i=0; i < n; i++ )
d->pkey[i] = mpi_copy( s->pkey[i] );
}
return d;
}
PKT_public_key *
copy_public_key( PKT_public_key *d, PKT_public_key *s )
{
return copy_public_key_new_namehash( d, s, NULL );
}
PKT_signature *
copy_signature( PKT_signature *d, PKT_signature *s )
{
int n, i;
if( !d )
d = m_alloc(sizeof *d);
memcpy( d, s, sizeof *d );
n = pubkey_get_nsig( s->pubkey_algo );
if( !n )
d->data[0] = cp_fake_data(s->data[0]);
else {
for(i=0; i < n; i++ )
d->data[i] = mpi_copy( s->data[i] );
}
d->hashed_data = cp_data_block(s->hashed_data);
d->unhashed_data = cp_data_block(s->unhashed_data);
return d;
}
PKT_user_id *
copy_user_id( PKT_user_id *d, PKT_user_id *s )
{
if( !d )
d = m_alloc(sizeof *d + s->len - 1 );
memcpy( d, s, sizeof *d + s->len - 1 );
return d;
}
void
release_secret_key_parts( PKT_secret_key *sk )
{
int n, i;
n = pubkey_get_nskey( sk->pubkey_algo );
if( !n ) {
m_free(sk->skey[0]);
sk->skey[0] = NULL;
}
for(i=0; i < n; i++ ) {
mpi_free( sk->skey[i] );
sk->skey[i] = NULL;
}
}
void
free_secret_key( PKT_secret_key *sk )
{
release_secret_key_parts( sk );
m_free(sk);
}
PKT_secret_key *
copy_secret_key( PKT_secret_key *d, PKT_secret_key *s )
{
int n, i;
if( !d )
d = m_alloc(sizeof *d);
memcpy( d, s, sizeof *d );
n = pubkey_get_nskey( s->pubkey_algo );
if( !n )
d->skey[0] = cp_fake_data(s->skey[0]);
else {
for(i=0; i < n; i++ )
d->skey[i] = mpi_copy( s->skey[i] );
}
return d;
}
void
free_comment( PKT_comment *rem )
{
m_free(rem);
}
void
free_user_id( PKT_user_id *uid )
{
m_free(uid);
}
void
free_compressed( PKT_compressed *zd )
{
if( zd->buf ) { /* have to skip some bytes */
/* don't have any information about the length, so
* we assume this is the last packet */
while( iobuf_get(zd->buf) != -1 )
;
}
m_free(zd);
}
void
free_encrypted( PKT_encrypted *ed )
{
if( ed->buf ) { /* have to skip some bytes */
if( iobuf_in_block_mode(ed->buf) ) {
while( iobuf_get(ed->buf) != -1 )
;
iobuf_set_block_mode(ed->buf, 0);
}
else {
for( ; ed->len; ed->len-- ) /* skip the packet */
iobuf_get(ed->buf);
}
}
m_free(ed);
}
void
free_plaintext( PKT_plaintext *pt )
{
if( pt->buf ) { /* have to skip some bytes */
if( iobuf_in_block_mode(pt->buf) ) {
while( iobuf_get(pt->buf) != -1 )
;
iobuf_set_block_mode(pt->buf, 0);
}
else {
for( ; pt->len; pt->len-- ) /* skip the packet */
iobuf_get(pt->buf);
}
}
m_free(pt);
}
/****************
* Free the packet in pkt.
*/
void
free_packet( PACKET *pkt )
{
if( !pkt || !pkt->pkt.generic )
return;
if( DBG_MEMORY )
log_debug("free_packet() type=%d\n", pkt->pkttype );
switch( pkt->pkttype ) {
case PKT_SIGNATURE:
free_seckey_enc( pkt->pkt.signature );
break;
case PKT_PUBKEY_ENC:
free_pubkey_enc( pkt->pkt.pubkey_enc );
break;
case PKT_SYMKEY_ENC:
free_symkey_enc( pkt->pkt.symkey_enc );
break;
case PKT_PUBLIC_KEY:
case PKT_PUBLIC_SUBKEY:
free_public_key( pkt->pkt.public_key );
break;
case PKT_SECRET_KEY:
case PKT_SECRET_SUBKEY:
free_secret_key( pkt->pkt.secret_key );
break;
case PKT_COMMENT:
free_comment( pkt->pkt.comment );
break;
case PKT_USER_ID:
free_user_id( pkt->pkt.user_id );
break;
case PKT_COMPRESSED:
free_compressed( pkt->pkt.compressed);
break;
case PKT_ENCRYPTED:
free_encrypted( pkt->pkt.encrypted );
break;
case PKT_PLAINTEXT:
free_plaintext( pkt->pkt.plaintext );
break;
default:
m_free( pkt->pkt.generic );
break;
}
pkt->pkt.generic = NULL;
}
/****************
* returns 0 if they match.
*/
int
cmp_public_keys( PKT_public_key *a, PKT_public_key *b )
{
int n, i;
if( a->timestamp != b->timestamp )
return -1;
if( a->expiredate != b->expiredate )
return -1;
if( a->pubkey_algo != b->pubkey_algo )
return -1;
n = pubkey_get_npkey( b->pubkey_algo );
if( !n )
return -1; /* can't compare due to unknown algorithm */
for(i=0; i < n; i++ ) {
if( mpi_cmp( a->pkey[i], b->pkey[i] ) )
return -1;
}
return 0;
}
/****************
* Returns 0 if they match.
* We only compare the public parts.
*/
int
cmp_secret_keys( PKT_secret_key *a, PKT_secret_key *b )
{
int n, i;
if( a->timestamp != b->timestamp )
return -1;
if( a->expiredate != b->expiredate )
return -1;
if( a->pubkey_algo != b->pubkey_algo )
return -1;
n = pubkey_get_npkey( b->pubkey_algo );
if( !n )
return -1; /* can't compare due to unknown algorithm */
for(i=0; i < n; i++ ) {
if( mpi_cmp( a->skey[i], b->skey[i] ) )
return -1;
}
return 0;
}
/****************
* Returns 0 if they match.
*/
int
cmp_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk )
{
int n, i;
if( pk->timestamp != sk->timestamp )
return -1;
if( pk->expiredate != sk->expiredate )
return -1;
if( pk->pubkey_algo != sk->pubkey_algo )
return -1;
n = pubkey_get_npkey( pk->pubkey_algo );
if( !n )
return -1; /* can't compare due to unknown algorithm */
for(i=0; i < n; i++ ) {
if( mpi_cmp( pk->pkey[i] , sk->skey[i] ) )
return -1;
}
return 0;
}
int
cmp_signatures( PKT_signature *a, PKT_signature *b )
{
int n, i;
if( a->keyid[0] != b->keyid[0] )
return -1;
if( a->keyid[1] != b->keyid[1] )
return -1;
if( a->pubkey_algo != b->pubkey_algo )
return -1;
n = pubkey_get_nsig( a->pubkey_algo );
if( !n )
return -1; /* can't compare due to unknown algorithm */
for(i=0; i < n; i++ ) {
if( mpi_cmp( a->data[i] , b->data[i] ) )
return -1;
}
return 0;
}
int
cmp_user_ids( PKT_user_id *a, PKT_user_id *b )
{
int res;
res = a->len - b->len;
if( !res )
res = memcmp( a->name, b->name, a->len );
return res;
}
diff --git a/g10/g10.c b/g10/g10.c
index 1f1fed5e5..8191ea03b 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -1,1435 +1,1435 @@
/* g10.c - The GnuPG utility (main for gpg)
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#define MAINTAINER_OPTIONS
#include "packet.h"
#include "iobuf.h"
#include "memory.h"
#include "util.h"
#include "main.h"
#include "options.h"
#include "keydb.h"
#include "mpi.h"
#include "cipher.h"
#include "filter.h"
#include "trustdb.h"
#include "ttyio.h"
#include "i18n.h"
#include "status.h"
#include "g10defs.h"
#ifndef IS_G10MAINT
#define IS_G10 1
#endif
enum cmd_and_opt_values { aNull = 0,
oArmor = 'a',
aDetachedSign = 'b',
aSym = 'c',
aDecrypt = 'd',
aEncr = 'e',
oKOption = 'k',
oDryRun = 'n',
oOutput = 'o',
oQuiet = 'q',
oRemote = 'r',
aSign = 's',
oTextmodeShort= 't',
oUser = 'u',
oVerbose = 'v',
oCompress = 'z',
oBatch = 500,
aClearsign,
aStore,
aKeygen,
aSignEncr,
aSignKey,
aListPackets,
aEditKey,
aDeleteKey,
aDeleteSecretKey,
aKMode,
aKModeC,
aImport,
aFastImport,
aVerify,
aListKeys,
aListSigs,
aListSecretKeys,
aExport,
aExportAll,
aExportSecret,
aCheckKeys,
aGenRevoke,
aPrimegen,
aPrintMD,
aPrintMDs,
aCheckTrustDB,
aUpdateTrustDB,
aFixTrustDB,
aListTrustDB,
aListTrustPath,
aExportOwnerTrust,
aImportOwnerTrust,
aDeArmor,
aEnArmor,
aGenRandom,
oTextmode,
oFingerprint,
oAnswerYes,
oAnswerNo,
oKeyring,
oSecretKeyring,
oDefaultKey,
oTrustedKey,
oOptions,
oDebug,
oDebugAll,
oStatusFD,
oNoComment,
oCompletesNeeded,
oMarginalsNeeded,
oMaxCertDepth,
oLoadExtension,
oRFC1991,
oCipherAlgo,
oDigestAlgo,
oCompressAlgo,
oPasswdFD,
oQuickRandom,
oNoVerbose,
oTrustDBName,
oNoSecmemWarn,
oNoArmor,
oNoDefKeyring,
oNoGreeting,
oNoOptions,
oNoBatch,
oHomedir,
oWithColons,
oSkipVerify,
oCompressKeys,
oCompressSigs,
oAlwaysTrust,
oEmuChecksumBug,
oRunAsShmCP,
oSetFilename,
oComment,
oThrowKeyid,
oForceV3Sigs,
oS2KMode,
oS2KDigest,
oS2KCipher,
oCharset,
oNotDashEscaped,
oEscapeFrom,
oLockOnce,
aTest };
static ARGPARSE_OPTS opts[] = {
{ 300, NULL, 0, N_("@Commands:\n ") },
#ifdef IS_G10
{ aSign, "sign", 256, N_("|[file]|make a signature")},
{ aClearsign, "clearsign", 256, N_("|[file]|make a clear text signature") },
{ aDetachedSign, "detach-sign", 256, N_("make a detached signature")},
{ aEncr, "encrypt", 256, N_("encrypt data")},
{ aSym, "symmetric", 256, N_("encryption only with symmetric cipher")},
{ aStore, "store", 256, N_("store only")},
{ aDecrypt, "decrypt", 256, N_("decrypt data (default)")},
{ aVerify, "verify" , 256, N_("verify a signature")},
#endif
{ aListKeys, "list-keys", 256, N_("list keys")},
{ aListSigs, "list-sigs", 256, N_("list keys and signatures")},
{ aCheckKeys, "check-sigs",256, N_("check key signatures")},
{ oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")},
{ aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")},
#ifdef IS_G10
{ aKeygen, "gen-key", 256, N_("generate a new key pair")},
#endif
{ aDeleteKey, "delete-key",256, N_("remove key from the public keyring")},
#ifdef IS_G10
{ aEditKey, "edit-key" ,256, N_("sign or edit a key")},
{ aGenRevoke, "gen-revoke",256, N_("generate a revocation certificate")},
#endif
{ aExport, "export" , 256, N_("export keys") },
{ aExportAll, "export-all" , 256, "@" },
{ aExportSecret, "export-secret-keys" , 256, "@" },
{ aImport, "import", 256 , N_("import/merge keys")},
{ aFastImport, "fast-import", 256 , "@"},
{ aListPackets, "list-packets",256,N_("list only the sequence of packets")},
#ifdef IS_G10MAINT
{ aExportOwnerTrust,
"export-ownertrust", 256, N_("export the ownertrust values")},
{ aImportOwnerTrust,
"import-ownertrust", 256 , N_("import ownertrust values")},
{ aUpdateTrustDB,
"update-trustdb",0 , N_("|[NAMES]|update the trust database")},
{ aCheckTrustDB,
"check-trustdb",0 , N_("|[NAMES]|check the trust database")},
{ aFixTrustDB, "fix-trustdb",0 , N_("fix a corrupted trust database")},
{ aDeArmor, "dearmor", 256, N_("De-Armor a file or stdin") },
{ aEnArmor, "enarmor", 256, N_("En-Armor a file or stdin") },
{ aPrintMD, "print-md" , 256, N_("|algo [files]|print message digests")},
{ aPrintMDs, "print-mds" , 256, N_("print all message digests")},
#ifdef MAINTAINER_OPTIONS
{ aPrimegen, "gen-prime" , 256, "@" },
{ aGenRandom, "gen-random" , 256, "@" },
#endif
#endif
{ 301, NULL, 0, N_("@\nOptions:\n ") },
{ oArmor, "armor", 0, N_("create ascii armored output")},
#ifdef IS_G10
{ oUser, "local-user",2, N_("use this user-id to sign or decrypt")},
{ oRemote, "remote-user", 2, N_("use this user-id for encryption")},
{ oCompress, NULL, 1, N_("|N|set compress level N (0 disables)") },
{ oTextmodeShort, NULL, 0, "@"},
{ oTextmode, "textmode", 0, N_("use canonical text mode")},
#endif
{ oOutput, "output", 2, N_("use as output file")},
{ oVerbose, "verbose", 0, N_("verbose") },
{ oQuiet, "quiet", 0, N_("be somewhat more quiet") },
{ oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") },
/* { oDryRun, "dry-run", 0, N_("do not make any changes") }, */
{ oBatch, "batch", 0, N_("batch mode: never ask")},
{ oAnswerYes, "yes", 0, N_("assume yes on most questions")},
{ oAnswerNo, "no", 0, N_("assume no on most questions")},
{ oKeyring, "keyring" ,2, N_("add this keyring to the list of keyrings")},
{ oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")},
{ oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")},
{ oCharset, "charset" , 2, N_("|NAME|set terminal charset to NAME") },
{ oOptions, "options" , 2, N_("read options from file")},
{ oDebug, "debug" ,4|16, N_("set debugging flags")},
{ oDebugAll, "debug-all" ,0, N_("enable full debugging")},
{ oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") },
{ oNoComment, "no-comment", 0, N_("do not write comment packets")},
{ oCompletesNeeded, "completes-needed", 1, N_("(default is 1)")},
{ oMarginalsNeeded, "marginals-needed", 1, N_("(default is 3)")},
{ oMaxCertDepth, "max-cert-depth", 1, "@" },
{ oTrustedKey, "trusted-key", 2, N_("|KEYID|ulimately trust this key")},
{ oLoadExtension, "load-extension" ,2, N_("|FILE|load extension module FILE")},
{ oRFC1991, "rfc1991", 0, N_("emulate the mode described in RFC1991")},
{ oS2KMode, "s2k-mode", 1, N_("|N|use passphrase mode N")},
{ oS2KDigest, "s2k-digest-algo",2,
N_("|NAME|use message digest algorithm NAME for passphrases")},
{ oS2KCipher, "s2k-cipher-algo",2,
N_("|NAME|use cipher algorithm NAME for passphrases")},
#ifdef IS_G10
{ oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")},
{ oDigestAlgo, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")},
{ oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")},
{ oThrowKeyid, "throw-keyid", 0, N_("throw keyid field of encrypted packets")},
#else /* some dummies */
{ oCipherAlgo, "cipher-algo", 2 , "@"},
{ oDigestAlgo, "digest-algo", 2 , "@"},
{ oCompressAlgo, "compress-algo", 1 , "@"},
#endif
#ifdef IS_G10
{ 302, NULL, 0, N_("@\nExamples:\n\n"
" -se -r Bob [file] sign and encrypt for user Bob\n"
" --clearsign [file] make a clear text signature\n"
" --detach-sign [file] make a detached signature\n"
" --list-keys [names] show keys\n"
" --fingerprint [names] show fingerprints\n" ) },
#endif
/* hidden options */
#ifdef IS_G10MAINT
{ aExportOwnerTrust, "list-ownertrust",0 , "@"}, /* alias */
{ aListTrustDB, "list-trustdb",0 , "@"},
{ aListTrustPath, "list-trust-path",0, "@"},
#endif
#ifdef IS_G10
{ oKOption, NULL, 0, "@"},
{ oPasswdFD, "passphrase-fd",1, "@" },
{ aSignKey, "sign-key" ,256, "@" }, /* alias for edit-key */
#endif
{ aDeleteSecretKey, "delete-secret-key",0, "@" },
{ oQuickRandom, "quick-random", 0, "@"},
{ oNoVerbose, "no-verbose", 0, "@"},
{ oTrustDBName, "trustdb-name", 2, "@" },
{ oNoSecmemWarn, "no-secmem-warning", 0, "@" }, /* used only by regression tests */
{ oNoArmor, "no-armor", 0, "@"},
{ oNoDefKeyring, "no-default-keyring", 0, "@" },
{ oNoGreeting, "no-greeting", 0, "@" },
{ oNoOptions, "no-options", 0, "@" }, /* shortcut for --options /dev/null */
{ oHomedir, "homedir", 2, "@" }, /* defaults to "~/.gnupg" */
{ oNoBatch, "no-batch", 0, "@" },
{ oWithColons, "with-colons", 0, "@"},
{ aListKeys, "list-key", 0, "@" }, /* alias */
{ aListSigs, "list-sig", 0, "@" }, /* alias */
{ aCheckKeys, "check-sig",0, "@" }, /* alias */
{ oSkipVerify, "skip-verify",0, "@" },
{ oCompressKeys, "compress-keys",0, "@"},
{ oCompressSigs, "compress-sigs",0, "@"},
{ oAlwaysTrust, "always-trust", 0, "@"},
{ oEmuChecksumBug, "emulate-checksum-bug", 0, "@"},
{ oRunAsShmCP, "run-as-shm-coprocess", 4, "@" },
{ oSetFilename, "set-filename", 2, "@" },
{ oComment, "comment", 2, "@" },
{ oNotDashEscaped, "not-dash-escaped", 0, "@" },
{ oEscapeFrom, "escape-from-lines", 0, "@" },
{ oLockOnce, "lock-once", 0, "@" },
{0} };
int g10_errors_seen = 0;
static int maybe_setuid = 1;
static char *build_list( const char *text,
const char *(*mapf)(int), int (*chkf)(int) );
static void set_cmd( enum cmd_and_opt_values *ret_cmd,
enum cmd_and_opt_values new_cmd );
#ifdef IS_G10MAINT
static void print_hex( byte *p, size_t n );
static void print_mds( const char *fname, int algo );
#endif
const char *
strusage( int level )
{
static char *digests, *pubkeys, *ciphers;
const char *p;
switch( level ) {
case 11: p =
#ifdef IS_G10MAINT
"gpgm (GnuPG)";
#else
"gpg (GnuPG)";
#endif
break;
case 13: p = VERSION; break;
case 17: p = PRINTABLE_OS_NAME; break;
case 19: p =
_("Please report bugs to <gnupg-bugs@gnu.org>.\n");
break;
case 1:
case 40: p =
#ifdef IS_G10MAINT
_("Usage: gpgm [options] [files] (-h for help)");
#else
_("Usage: gpg [options] [files] (-h for help)");
#endif
break;
case 41: p =
#ifdef IS_G10MAINT
_("Syntax: gpgm [options] [files]\n"
"GnuPG maintenance utility\n");
#else
_("Syntax: gpg [options] [files]\n"
"sign, check, encrypt or decrypt\n"
"default operation depends on the input data\n");
#endif
break;
case 31: p = _("\nSupported algorithms:\n"); break;
case 32:
if( !ciphers )
ciphers = build_list("Cipher: ", cipher_algo_to_string,
check_cipher_algo );
p = ciphers;
break;
case 33:
if( !pubkeys )
pubkeys = build_list("Pubkey: ", pubkey_algo_to_string,
check_pubkey_algo );
p = pubkeys;
break;
case 34:
if( !digests )
digests = build_list("Hash: ", digest_algo_to_string,
check_digest_algo );
p = digests;
break;
default: p = default_strusage(level);
}
return p;
}
static char *
build_list( const char *text, const char * (*mapf)(int), int (*chkf)(int) )
{
int i;
const char *s;
size_t n=strlen(text)+2;
char *list, *p;
if( maybe_setuid )
secmem_init( 0 ); /* drop setuid */
for(i=1; i < 110; i++ )
if( !chkf(i) && (s=mapf(i)) )
n += strlen(s) + 2;
list = m_alloc( 21 + n ); *list = 0;
for(p=NULL, i=1; i < 110; i++ ) {
if( !chkf(i) && (s=mapf(i)) ) {
if( !p )
p = stpcpy( list, text );
else
p = stpcpy( p, ", ");
p = stpcpy(p, s );
}
}
if( p )
p = stpcpy(p, "\n" );
return list;
}
static void
i18n_init(void)
{
#ifdef ENABLE_NLS
#ifdef HAVE_LC_MESSAGES
setlocale( LC_TIME, "" );
setlocale( LC_MESSAGES, "" );
#else
setlocale( LC_ALL, "" );
#endif
bindtextdomain( PACKAGE, G10_LOCALEDIR );
textdomain( PACKAGE );
#endif
}
static void
wrong_args( const char *text)
{
#ifdef IS_G10MAINT
fputs(_("usage: gpgm [options] "),stderr);
#else
fputs(_("usage: gpg [options] "),stderr);
#endif
fputs(text,stderr);
putc('\n',stderr);
g10_exit(2);
}
static void
set_debug(void)
{
if( opt.debug & DBG_MEMORY_VALUE )
memory_debug_mode = 1;
if( opt.debug & DBG_MEMSTAT_VALUE )
memory_stat_debug_mode = 1;
if( opt.debug & DBG_MPI_VALUE )
mpi_debug_mode = 1;
if( opt.debug & DBG_CIPHER_VALUE )
g10c_debug_mode = 1;
if( opt.debug & DBG_IOBUF_VALUE )
iobuf_debug_mode = 1;
}
static void
set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd )
{
enum cmd_and_opt_values cmd = *ret_cmd;
if( !cmd || cmd == new_cmd )
cmd = new_cmd;
else if( cmd == aSign && new_cmd == aEncr )
cmd = aSignEncr;
else if( cmd == aEncr && new_cmd == aSign )
cmd = aSignEncr;
else if( cmd == aKMode && new_cmd == aSym )
cmd = aKModeC;
else if( ( cmd == aSign && new_cmd == aClearsign )
|| ( cmd == aClearsign && new_cmd == aSign ) )
cmd = aClearsign;
else {
log_error(_("conflicting commands\n"));
g10_exit(2);
}
*ret_cmd = cmd;
}
int
main( int argc, char **argv )
{
ARGPARSE_ARGS pargs;
IOBUF a;
int rc=0;
int orig_argc;
char **orig_argv;
const char *fname;
STRLIST sl, remusr= NULL, locusr=NULL;
STRLIST nrings=NULL, sec_nrings=NULL;
armor_filter_context_t afx;
int detached_sig = 0;
FILE *configfp = NULL;
char *configname = NULL;
unsigned configlineno;
int parse_debug = 0;
int default_config =1;
int default_keyring = 1;
int greeting = 1;
enum cmd_and_opt_values cmd = 0;
const char *trustdb_name = NULL;
char *def_cipher_string = NULL;
char *def_digest_string = NULL;
char *s2k_cipher_string = NULL;
char *s2k_digest_string = NULL;
int pwfd = -1;
#ifdef USE_SHM_COPROCESSING
ulong requested_shm_size=0;
#endif
trap_unaligned();
secmem_set_flags( secmem_get_flags() | 2 ); /* suspend warnings */
#ifdef IS_G10MAINT
secmem_init( 0 ); /* disable use of secmem */
maybe_setuid = 0;
log_set_name("gpgm");
#else
/* Please note that we may running SUID(ROOT), so be very CAREFUL
* when adding any stuff between here and the call to
* secmem_init() somewhere after the option parsing
*/
log_set_name("gpg");
secure_random_alloc(); /* put random number into secure memory */
disable_core_dumps();
#endif
init_signals();
i18n_init();
opt.compress = -1; /* defaults to standard compress level */
/* fixme: set the next two to zero and decide where used */
opt.def_cipher_algo = 0;
opt.def_digest_algo = 0;
opt.def_compress_algo = 2;
opt.s2k_mode = 1; /* salted */
opt.s2k_digest_algo = DIGEST_ALGO_RMD160;
opt.s2k_cipher_algo = CIPHER_ALGO_BLOWFISH;
opt.completes_needed = 1;
opt.marginals_needed = 3;
opt.max_cert_depth = 5;
opt.homedir = getenv("GNUPGHOME");
if( !opt.homedir || !*opt.homedir ) {
#ifdef __MINGW32__
opt.homedir = "c:/gnupg";
#else
opt.homedir = "~/.gnupg";
#endif
}
/* check whether we have a config file on the commandline */
orig_argc = argc;
orig_argv = argv;
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1|(1<<6); /* do not remove the args, ignore version */
while( arg_parse( &pargs, opts) ) {
if( pargs.r_opt == oDebug || pargs.r_opt == oDebugAll )
parse_debug++;
else if( pargs.r_opt == oOptions ) {
/* yes there is one, so we do not try the default one, but
* read the option file when it is encountered at the commandline
*/
default_config = 0;
}
else if( pargs.r_opt == oNoOptions )
default_config = 0; /* --no-options */
else if( pargs.r_opt == oHomedir )
opt.homedir = pargs.r.ret_str;
#ifdef USE_SHM_COPROCESSING
else if( pargs.r_opt == oRunAsShmCP ) {
/* does not make sense in a options file, we do it here,
* so that we are the able to drop setuid as soon as possible */
opt.shm_coprocess = 1;
requested_shm_size = pargs.r.ret_ulong;
}
#endif
}
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess ) {
#ifdef IS_G10
init_shm_coprocessing(requested_shm_size, 1 );
#else
init_shm_coprocessing(requested_shm_size, 0 );
#endif
}
#endif
#ifdef IS_G10
/* initialize the secure memory. */
secmem_init( 16384 );
maybe_setuid = 0;
/* Okay, we are now working under our real uid */
#endif
if( default_config )
configname = make_filename(opt.homedir, "options", NULL );
argc = orig_argc;
argv = orig_argv;
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1; /* do not remove the args */
next_pass:
if( configname ) {
configlineno = 0;
configfp = fopen( configname, "r" );
if( !configfp ) {
if( default_config ) {
if( parse_debug )
log_info(_("NOTE: no default option file '%s'\n"),
configname );
}
else {
log_error(_("option file '%s': %s\n"),
configname, strerror(errno) );
g10_exit(2);
}
m_free(configname); configname = NULL;
}
if( parse_debug && configname )
log_info(_("reading options from '%s'\n"), configname );
default_config = 0;
}
while( optfile_parse( configfp, configname, &configlineno,
&pargs, opts) ) {
switch( pargs.r_opt ) {
case aCheckKeys: set_cmd( &cmd, aCheckKeys); break;
case aListPackets: set_cmd( &cmd, aListPackets); break;
case aImport: set_cmd( &cmd, aImport); break;
case aFastImport: set_cmd( &cmd, aFastImport); break;
case aExport: set_cmd( &cmd, aExport); break;
case aExportAll: set_cmd( &cmd, aExportAll); break;
case aListKeys: set_cmd( &cmd, aListKeys); break;
case aListSigs: set_cmd( &cmd, aListSigs); break;
case aExportSecret: set_cmd( &cmd, aExportSecret); break;
case aDeleteSecretKey: set_cmd( &cmd, aDeleteSecretKey); break;
case aDeleteKey: set_cmd( &cmd, aDeleteKey); break;
#ifdef IS_G10
case aDetachedSign: detached_sig = 1; set_cmd( &cmd, aSign ); break;
case aSym: set_cmd( &cmd, aSym); break;
case aDecrypt: set_cmd( &cmd, aDecrypt); break;
case aEncr: set_cmd( &cmd, aEncr); break;
case aSign: set_cmd( &cmd, aSign ); break;
case aKeygen: set_cmd( &cmd, aKeygen); break;
case aSignKey: set_cmd( &cmd, aSignKey); break;
case aStore: set_cmd( &cmd, aStore); break;
case aEditKey: set_cmd( &cmd, aEditKey); break;
case aClearsign: set_cmd( &cmd, aClearsign); break;
case aGenRevoke: set_cmd( &cmd, aGenRevoke); break;
case aVerify: set_cmd( &cmd, aVerify); break;
#else
#ifdef MAINTAINER_OPTIONS
case aPrimegen: set_cmd( &cmd, aPrimegen); break;
case aGenRandom: set_cmd( &cmd, aGenRandom); break;
#endif
case aPrintMD: set_cmd( &cmd, aPrintMD); break;
case aPrintMDs: set_cmd( &cmd, aPrintMDs); break;
case aListTrustDB: set_cmd( &cmd, aListTrustDB); break;
case aCheckTrustDB: set_cmd( &cmd, aCheckTrustDB); break;
case aUpdateTrustDB: set_cmd( &cmd, aUpdateTrustDB); break;
case aFixTrustDB: set_cmd( &cmd, aFixTrustDB); break;
case aListTrustPath: set_cmd( &cmd, aListTrustPath); break;
case aDeArmor: set_cmd( &cmd, aDeArmor); break;
case aEnArmor: set_cmd( &cmd, aEnArmor); break;
case aExportOwnerTrust: set_cmd( &cmd, aExportOwnerTrust); break;
case aImportOwnerTrust: set_cmd( &cmd, aImportOwnerTrust); break;
#endif /* IS_G10MAINT */
case oArmor: opt.armor = 1; opt.no_armor=0; break;
case oOutput: opt.outfile = pargs.r.ret_str; break;
case oQuiet: opt.quiet = 1; break;
case oVerbose: g10_opt_verbose++;
opt.verbose++; opt.list_sigs=1; break;
case oKOption: set_cmd( &cmd, aKMode ); break;
case oBatch: opt.batch = 1; greeting = 0; break;
case oAnswerYes: opt.answer_yes = 1; break;
case oAnswerNo: opt.answer_no = 1; break;
case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break;
case oDebug: opt.debug |= pargs.r.ret_ulong; break;
case oDebugAll: opt.debug = ~0; break;
case oStatusFD: set_status_fd( pargs.r.ret_int ); break;
case oFingerprint: opt.fingerprint++; break;
case oSecretKeyring: append_to_strlist( &sec_nrings, pargs.r.ret_str); break;
case oOptions:
/* config files may not be nested (silently ignore them) */
if( !configfp ) {
m_free(configname);
configname = m_strdup(pargs.r.ret_str);
goto next_pass;
}
break;
case oNoArmor: opt.no_armor=1; opt.armor=0; break;
case oNoDefKeyring: default_keyring = 0; break;
case oNoGreeting: greeting = 0; break;
case oNoVerbose: g10_opt_verbose = 0;
opt.verbose = 0; opt.list_sigs=0; break;
case oQuickRandom: quick_random_gen(1); break;
case oNoComment: opt.no_comment=1; break;
case oCompletesNeeded: opt.completes_needed = pargs.r.ret_int; break;
case oMarginalsNeeded: opt.marginals_needed = pargs.r.ret_int; break;
case oMaxCertDepth: opt.max_cert_depth = pargs.r.ret_int; break;
case oTrustDBName: trustdb_name = pargs.r.ret_str; break;
case oDefaultKey: opt.def_secret_key = pargs.r.ret_str; break;
case oTrustedKey: register_trusted_key( pargs.r.ret_str ); break;
case oNoOptions: break; /* no-options */
case oHomedir: opt.homedir = pargs.r.ret_str; break;
case oNoBatch: opt.batch = 0; break;
case oWithColons: opt.with_colons=':'; break;
case oSkipVerify: opt.skip_verify=1; break;
case oCompressAlgo: opt.def_compress_algo = pargs.r.ret_int; break;
case oCompressKeys: opt.compress_keys = 1; break;
case aListSecretKeys: set_cmd( &cmd, aListSecretKeys); break;
case oAlwaysTrust: opt.always_trust = 1; break;
case oLoadExtension:
register_cipher_extension(orig_argc? *orig_argv:NULL,
pargs.r.ret_str);
break;
case oRFC1991:
opt.rfc1991 = 1;
opt.no_comment = 1;
opt.escape_from = 1;
break;
case oEmuChecksumBug: opt.emulate_bugs |= EMUBUG_GPGCHKSUM; break;
case oCompressSigs: opt.compress_sigs = 1; break;
case oRunAsShmCP:
#ifndef USE_SHM_COPROCESSING
/* not possible in the option file,
* but we print the warning here anyway */
log_error("shared memory coprocessing is not available\n");
#endif
break;
case oSetFilename: opt.set_filename = pargs.r.ret_str; break;
case oComment: opt.comment_string = pargs.r.ret_str; break;
case oThrowKeyid: opt.throw_keyid = 1; break;
case oForceV3Sigs: opt.force_v3_sigs = 1; break;
case oS2KMode: opt.s2k_mode = pargs.r.ret_int; break;
case oS2KDigest: s2k_digest_string = m_strdup(pargs.r.ret_str); break;
case oS2KCipher: s2k_cipher_string = m_strdup(pargs.r.ret_str); break;
#ifdef IS_G10
case oRemote: /* store the remote users */
sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str));
strcpy(sl->d, pargs.r.ret_str);
sl->next = remusr;
remusr = sl;
break;
case oTextmodeShort: opt.textmode = 2; break;
case oTextmode: opt.textmode=1; break;
case oUser: /* store the local users */
sl = m_alloc( sizeof *sl + strlen(pargs.r.ret_str));
strcpy(sl->d, pargs.r.ret_str);
sl->next = locusr;
locusr = sl;
break;
case oCompress: opt.compress = pargs.r.ret_int; break;
case oPasswdFD: pwfd = pargs.r.ret_int; break;
case oCipherAlgo: def_cipher_string = m_strdup(pargs.r.ret_str); break;
case oDigestAlgo: def_digest_string = m_strdup(pargs.r.ret_str); break;
case oNoSecmemWarn: secmem_set_flags( secmem_get_flags() | 1 ); break;
#else
case oCipherAlgo:
case oDigestAlgo:
case oNoSecmemWarn:
break; /* dummies */
#endif
case oCharset:
if( set_native_charset( pargs.r.ret_str ) )
log_error(_("%s is not a valid character set\n"),
pargs.r.ret_str);
break;
case oNotDashEscaped: opt.not_dash_escaped = 1; break;
case oEscapeFrom: opt.escape_from = 1; break;
case oLockOnce: opt.lock_once = 1; break;
default : pargs.err = configfp? 1:2; break;
}
}
if( configfp ) {
fclose( configfp );
configfp = NULL;
m_free(configname); configname = NULL;
goto next_pass;
}
m_free( configname ); configname = NULL;
if( log_get_errorcount(0) )
g10_exit(2);
if( greeting ) {
tty_printf("%s %s; %s\n", strusage(11), strusage(13), strusage(14) );
tty_printf("%s\n", strusage(15) );
}
secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */
set_debug();
/* must do this after dropping setuid, because string_to...
* may try to load an module */
if( def_cipher_string ) {
opt.def_cipher_algo = string_to_cipher_algo(def_cipher_string);
m_free(def_cipher_string); def_cipher_string = NULL;
if( check_cipher_algo(opt.def_cipher_algo) )
log_error(_("selected cipher algorithm is invalid\n"));
}
if( def_digest_string ) {
opt.def_digest_algo = string_to_digest_algo(def_digest_string);
m_free(def_digest_string); def_digest_string = NULL;
if( check_digest_algo(opt.def_digest_algo) )
log_error(_("selected digest algorithm is invalid\n"));
}
if( s2k_cipher_string ) {
opt.s2k_cipher_algo = string_to_cipher_algo(s2k_cipher_string);
m_free(s2k_cipher_string); s2k_cipher_string = NULL;
if( check_cipher_algo(opt.s2k_cipher_algo) )
log_error(_("selected cipher algorithm is invalid\n"));
}
if( s2k_digest_string ) {
opt.s2k_digest_algo = string_to_digest_algo(s2k_digest_string);
m_free(s2k_digest_string); s2k_digest_string = NULL;
if( check_digest_algo(opt.s2k_digest_algo) )
log_error(_("selected digest algorithm is invalid\n"));
}
if( opt.def_compress_algo < 1 || opt.def_compress_algo > 2 )
log_error(_("compress algorithm must be in range %d..%d\n"), 1, 2);
if( opt.completes_needed < 1 )
log_error(_("completes-needed must be greater than 0\n"));
if( opt.marginals_needed < 2 )
log_error(_("marginals-needed must be greater than 1\n"));
if( opt.max_cert_depth < 1 || opt.max_cert_depth > 255 )
log_error(_("max-cert-depth must be in range 1 to 255\n"));
switch( opt.s2k_mode ) {
case 0:
log_info(_("NOTE: simple S2K mode (0) is strongly discouraged\n"));
break;
case 1: case 3: break;
default:
log_error(_("invalid S2K mode; must be 0, 1 or 3\n"));
}
{ const char *p = strusage(13);
for( ; *p && (isdigit(*p) || *p=='.'); p++ )
;
if( *p )
log_info("NOTE: This is a development version!\n");
}
if( log_get_errorcount(0) )
g10_exit(2);
if( !cmd && opt.fingerprint )
set_cmd( &cmd, aListKeys);
if( cmd == aKMode || cmd == aKModeC ) { /* kludge to be compatible to pgp */
if( cmd == aKModeC ) {
opt.fingerprint = 1;
cmd = aKMode;
}
opt.list_sigs = 0;
if( opt.verbose > 2 )
opt.check_sigs++;
if( opt.verbose > 1 )
opt.list_sigs++;
opt.verbose = opt.verbose > 1;
g10_opt_verbose = opt.verbose;
}
/* kludge to let -sat generate a clear text signature */
if( opt.textmode == 2 && !detached_sig && opt.armor && cmd == aSign )
cmd = aClearsign;
if( opt.verbose > 1 )
set_packet_list_mode(1);
/* add the keyrings, but not for some special commands and
* not in case of "-kvv userid keyring" */
if( cmd != aDeArmor && cmd != aEnArmor
&& !(cmd == aKMode && argc == 2 ) ) {
if( !sec_nrings || default_keyring ) /* add default secret rings */
add_keyblock_resource("secring.gpg", 0, 1);
for(sl = sec_nrings; sl; sl = sl->next )
add_keyblock_resource( sl->d, 0, 1 );
if( !nrings || default_keyring ) /* add default ring */
add_keyblock_resource("pubring.gpg", 0, 0);
for(sl = nrings; sl; sl = sl->next )
add_keyblock_resource( sl->d, 0, 0 );
}
FREE_STRLIST(nrings);
FREE_STRLIST(sec_nrings);
if( pwfd != -1 ) /* read the passphrase now. */
read_passphrase_from_fd( pwfd );
fname = argc? *argv : NULL;
switch( cmd ) {
case aPrimegen:
case aPrintMD:
case aPrintMDs:
case aGenRandom:
case aDeArmor:
case aEnArmor:
case aFixTrustDB:
break;
case aKMode:
case aListKeys:
case aListSecretKeys:
case aCheckKeys:
if( opt.with_colons ) /* need this to list the trust */
rc = init_trustdb(1, trustdb_name );
break;
case aExportOwnerTrust: rc = init_trustdb( 0, trustdb_name ); break;
case aListTrustDB: rc = init_trustdb( argc? 1:0, trustdb_name ); break;
default: rc = init_trustdb(1, trustdb_name ); break;
}
if( rc )
log_error(_("failed to initialize the TrustDB: %s\n"), g10_errstr(rc));
switch( cmd ) {
case aStore: /* only store the file */
if( argc > 1 )
wrong_args(_("--store [filename]"));
if( (rc = encode_store(fname)) )
log_error_f( print_fname_stdin(fname),
"store failed: %s\n", g10_errstr(rc) );
break;
#ifdef IS_G10
case aSym: /* encrypt the given file only with the symmetric cipher */
if( argc > 1 )
wrong_args(_("--symmetric [filename]"));
if( (rc = encode_symmetric(fname)) )
log_error_f(print_fname_stdin(fname),
"symmetric encryption failed: %s\n",g10_errstr(rc) );
break;
case aEncr: /* encrypt the given file */
if( argc > 1 )
wrong_args(_("--encrypt [filename]"));
if( (rc = encode_crypt(fname,remusr)) )
log_error("%s: encryption failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
break;
case aSign: /* sign the given file */
sl = NULL;
if( detached_sig ) { /* sign all files */
for( ; argc; argc--, argv++ )
add_to_strlist( &sl, *argv );
}
else {
if( argc > 1 )
wrong_args(_("--sign [filename]"));
if( argc ) {
sl = m_alloc_clear( sizeof *sl + strlen(fname));
strcpy(sl->d, fname);
}
}
if( (rc = sign_file( sl, detached_sig, locusr, 0, NULL, NULL)) )
log_error("signing failed: %s\n", g10_errstr(rc) );
free_strlist(sl);
break;
case aSignEncr: /* sign and encrypt the given file */
if( argc > 1 )
wrong_args(_("--sign --encrypt [filename]"));
if( argc ) {
sl = m_alloc_clear( sizeof *sl + strlen(fname));
strcpy(sl->d, fname);
}
else
sl = NULL;
if( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) )
log_error("%s: sign+encrypt failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
free_strlist(sl);
break;
case aClearsign: /* make a clearsig */
if( argc > 1 )
wrong_args(_("--clearsign [filename]"));
if( (rc = clearsign_file(fname, locusr, NULL)) )
log_error("%s: clearsign failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
break;
case aVerify:
if( (rc = verify_signatures( argc, argv ) ))
log_error("verify signatures failed: %s\n", g10_errstr(rc) );
break;
case aDecrypt:
if( argc > 1 )
wrong_args(_("--decrypt [filename]"));
if( (rc = decrypt_message( fname ) ))
log_error("decrypt_message failed: %s\n", g10_errstr(rc) );
break;
case aSignKey: /* sign the key given as argument */
case aEditKey: /* Edit a key signature */
if( !argc )
wrong_args(_("--edit-key username [commands]"));
if( argc > 1 ) {
sl = NULL;
for( argc--, argv++ ; argc; argc--, argv++ )
append_to_strlist( &sl, *argv );
keyedit_menu( fname, locusr, sl );
free_strlist(sl);
}
else
keyedit_menu(fname, locusr, NULL );
break;
#endif /* IS_G10 */
case aDeleteSecretKey:
if( argc != 1 )
wrong_args(_("--delete-secret-key username"));
case aDeleteKey:
if( argc != 1 )
wrong_args(_("--delete-key username"));
/* note: fname is the user id! */
if( (rc = delete_key(fname, cmd==aDeleteSecretKey)) )
log_error("%s: delete key failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
break;
case aCheckKeys:
opt.check_sigs = 1;
case aListSigs:
opt.list_sigs = 1;
case aListKeys:
public_key_list( argc, argv );
break;
case aListSecretKeys:
secret_key_list( argc, argv );
break;
case aKMode: /* list keyring */
if( argc < 2 ) /* -kv [userid] */
public_key_list( (argc && **argv)? 1:0, argv );
else if( argc == 2 ) { /* -kv userid keyring */
if( access( argv[1], R_OK ) ) {
log_error(_("can't open %s: %s\n"),
print_fname_stdin(argv[1]), strerror(errno));
}
else {
/* add keyring (default keyrings are not registered in this
* special case */
add_keyblock_resource( argv[1], 0, 0 );
public_key_list( **argv?1:0, argv );
}
}
else
wrong_args(_("-k[v][v][v][c] [userid] [keyring]") );
break;
#ifdef IS_G10
case aKeygen: /* generate a key (interactive) */
if( argc )
wrong_args("--gen-key");
generate_keypair();
break;
#endif
case aFastImport:
case aImport:
if( !argc ) {
rc = import_keys( NULL, (cmd == aFastImport) );
if( rc )
log_error("import failed: %s\n", g10_errstr(rc) );
}
for( ; argc; argc--, argv++ ) {
rc = import_keys( *argv, (cmd == aFastImport) );
if( rc )
log_error("import from '%s' failed: %s\n",
*argv, g10_errstr(rc) );
}
break;
case aExport:
case aExportAll:
sl = NULL;
for( ; argc; argc--, argv++ )
add_to_strlist( &sl, *argv );
export_pubkeys( sl, (cmd == aExport) );
free_strlist(sl);
break;
case aExportSecret:
sl = NULL;
for( ; argc; argc--, argv++ )
add_to_strlist( &sl, *argv );
export_seckeys( sl );
free_strlist(sl);
break;
#ifdef IS_G10
case aGenRevoke:
if( argc != 1 )
wrong_args("--gen-revoke user-id");
gen_revoke( *argv );
break;
#endif
#ifdef IS_G10MAINT
case aDeArmor:
if( argc > 1 )
wrong_args("--dearmor [file]");
rc = dearmor_file( argc? *argv: NULL );
if( rc )
log_error(_("dearmoring failed: %s\n"), g10_errstr(rc));
break;
case aEnArmor:
if( argc > 1 )
wrong_args("--enarmor [file]");
rc = enarmor_file( argc? *argv: NULL );
if( rc )
log_error(_("enarmoring failed: %s\n"), g10_errstr(rc));
break;
#ifdef MAINTAINER_OPTIONS
case aPrimegen:
if( argc == 1 ) {
mpi_print( stdout, generate_public_prime( atoi(argv[0]) ), 1);
putchar('\n');
}
else if( argc == 2 ) {
mpi_print( stdout, generate_elg_prime( 0, atoi(argv[0]),
atoi(argv[1]), NULL,NULL ), 1);
putchar('\n');
}
else if( argc == 3 ) {
MPI g = mpi_alloc(1);
mpi_print( stdout, generate_elg_prime( 0, atoi(argv[0]),
atoi(argv[1]), g, NULL ), 1);
printf("\nGenerator: ");
mpi_print( stdout, g, 1 );
putchar('\n');
mpi_free(g);
}
else if( argc == 4 ) {
mpi_print( stdout, generate_elg_prime( 1, atoi(argv[0]),
atoi(argv[1]), NULL,NULL ), 1);
putchar('\n');
}
else
usage(1);
break;
#endif /* MAINTAINER OPTIONS */
#ifdef MAINTAINER_OPTIONS
case aGenRandom:
if( argc < 1 || argc > 2 )
wrong_args("--gen-random level [hex]");
{
int c;
int level = atoi(*argv);
for(;;) {
byte *p;
if( argc == 2 ) {
p = get_random_bits( 8, level, 0);
printf("%02x", *p );
fflush(stdout);
}
else {
p = get_random_bits( 800, level, 0);
for(c=0; c < 100; c++ )
putchar( p[c] );
}
m_free(p);
}
}
break;
#endif /* MAINTAINER OPTIONS */
case aPrintMD:
if( argc < 1)
wrong_args("--print-md algo [file]");
else {
int algo = string_to_digest_algo(*argv);
if( !algo )
log_error(_("invalid hash algorithm '%s'\n"), *argv );
else {
argc--; argv++;
if( !argc )
print_mds(NULL, algo);
else {
for(; argc; argc--, argv++ )
print_mds(*argv, algo);
}
}
}
break;
case aPrintMDs:
if( !argc )
print_mds(NULL,0);
else {
for(; argc; argc--, argv++ )
print_mds(*argv,0);
}
break;
case aListTrustDB:
if( !argc )
list_trustdb(NULL);
else {
for( ; argc; argc--, argv++ )
list_trustdb( *argv );
}
break;
case aUpdateTrustDB:
if( argc )
wrong_args("--update-trustdb");
update_trustdb();
break;
case aCheckTrustDB:
if( !argc )
check_trustdb(NULL);
else {
for( ; argc; argc--, argv++ )
check_trustdb( *argv );
}
break;
case aFixTrustDB:
log_error("this command ist not yet implemented.\"\n");
log_error("A workaround is to use \"--export-ownertrust\", remove\n");
log_error("the trustdb file and do an \"--import-ownertrust\".\n" );
break;
case aListTrustPath:
if( !argc )
wrong_args("--list-trust-path <usernames>");
for( ; argc; argc--, argv++ )
list_trust_path( *argv );
break;
case aExportOwnerTrust:
if( argc )
wrong_args("--export-ownertrust");
export_ownertrust();
break;
case aImportOwnerTrust:
if( argc > 1 )
wrong_args("--import-ownertrust [file]");
import_ownertrust( argc? *argv:NULL );
break;
#endif /* IS_G10MAINT */
case aListPackets:
opt.list_packets=1;
default:
/* fixme: g10maint should do regular maintenace tasks here */
if( argc > 1 )
wrong_args(_("[filename]"));
/* Issue some output for the unix newbie */
if( !fname && !opt.outfile && isatty( fileno(stdin) )
&& isatty( fileno(stdout) ) && isatty( fileno(stderr) ) )
log_info(_("Go ahead and type your message ...\n"));
if( !(a = iobuf_open(fname)) )
log_error(_("can't open '%s'\n"), print_fname_stdin(fname));
else {
if( !opt.no_armor ) {
if( use_armor_filter( a ) ) {
memset( &afx, 0, sizeof afx);
iobuf_push_filter( a, armor_filter, &afx );
}
}
if( cmd == aListPackets ) {
set_packet_list_mode(1);
opt.list_packets=1;
}
proc_packets( a );
iobuf_close(a);
}
break;
}
/* cleanup */
FREE_STRLIST(remusr);
FREE_STRLIST(locusr);
g10_exit(0);
return 8; /*NEVER REACHED*/
}
void
g10_exit( int rc )
{
if( opt.debug & DBG_MEMSTAT_VALUE )
m_print_stats("on exit");
if( opt.debug )
secmem_dump_stats();
secmem_term();
rc = rc? rc : log_get_errorcount(0)? 2 :
g10_errors_seen? 1 : 0;
/*write_status( STATUS_LEAVE );*/
exit(rc );
}
#ifdef IS_G10MAINT
static void
print_hex( byte *p, size_t n )
{
int i;
if( n == 20 ) {
for(i=0; i < n ; i++, i++, p += 2 ) {
if( i )
putchar(' ');
if( i == 10 )
putchar(' ');
printf("%02X%02X", *p, p[1] );
}
}
else if( n == 24 ) {
for(i=0; i < n ; i += 4, p += 4 ) {
if( i )
putchar(' ');
if( i == 12 )
putchar(' ');
printf("%02X%02X%02X%02X", *p, p[1], p[2], p[3] );
}
}
else {
for(i=0; i < n ; i++, p++ ) {
if( i )
putchar(' ');
if( i && !(i%8) )
putchar(' ');
printf("%02X", *p );
}
}
}
static void
print_mds( const char *fname, int algo )
{
FILE *fp;
char buf[1024];
size_t n;
MD_HANDLE md;
char *pname;
if( !fname ) {
fp = stdin;
pname = m_strdup("[stdin]: ");
}
else {
pname = m_alloc(strlen(fname)+3);
strcpy(stpcpy(pname,fname),": ");
fp = fopen( fname, "rb" );
}
if( !fp ) {
log_error("%s%s\n", pname, strerror(errno) );
m_free(pname);
return;
}
md = md_open( 0, 0 );
if( algo )
md_enable( md, algo );
else {
md_enable( md, DIGEST_ALGO_MD5 );
md_enable( md, DIGEST_ALGO_SHA1 );
md_enable( md, DIGEST_ALGO_RMD160 );
if( !check_digest_algo(DIGEST_ALGO_TIGER) )
md_enable( md, DIGEST_ALGO_TIGER );
}
while( (n=fread( buf, 1, DIM(buf), fp )) )
md_write( md, buf, n );
if( ferror(fp) )
log_error("%s%s\n", pname, strerror(errno) );
else {
md_final(md);
if( algo ) {
if( fname )
fputs( pname, stdout );
print_hex(md_read(md, algo), md_digest_length(algo) );
}
else {
printf( "%s MD5 = ", fname?pname:"" );
print_hex(md_read(md, DIGEST_ALGO_MD5), 16 );
printf("\n%s SHA1 = ", fname?pname:"" );
print_hex(md_read(md, DIGEST_ALGO_SHA1), 20 );
printf("\n%sRMD160 = ", fname?pname:"" );
print_hex(md_read(md, DIGEST_ALGO_RMD160), 20 );
if( !check_digest_algo(DIGEST_ALGO_TIGER) ) {
printf("\n%s TIGER = ", fname?pname:"" );
print_hex(md_read(md, DIGEST_ALGO_TIGER), 24 );
}
}
putchar('\n');
}
md_close(md);
if( fp != stdin )
fclose(fp);
}
#endif /* IS_G10MAINT */
diff --git a/g10/getkey.c b/g10/getkey.c
index 65c0ae495..f31529910 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -1,1459 +1,1491 @@
/* getkey.c - Get a key from the database
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
*/
#define DEFINES_GETKEY_CTX 1
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include "util.h"
#include "packet.h"
#include "memory.h"
#include "iobuf.h"
#include "keydb.h"
#include "options.h"
#include "main.h"
#include "i18n.h"
#define MAX_UNK_CACHE_ENTRIES 1000 /* we use a linked list - so I guess
* this is a reasonable limit */
#define MAX_PK_CACHE_ENTRIES 50
#define MAX_UID_CACHE_ENTRIES 50
struct getkey_ctx_s {
int mode;
int internal;
u32 keyid[2];
char *namebuf;
const char *name;
int primary;
KBNODE keyblock;
KBPOS kbpos;
int last_rc;
ulong count;
};
static struct {
int any;
int okay_count;
int nokey_count;
int error_count;
} lkup_stats[21];
#if MAX_UNK_CACHE_ENTRIES
typedef struct keyid_list {
struct keyid_list *next;
u32 keyid[2];
} *keyid_list_t;
static keyid_list_t unknown_keyids;
static int unk_cache_entries; /* number of entries in unknown keys cache */
static int unk_cache_disabled;
#endif
#if MAX_PK_CACHE_ENTRIES
typedef struct pk_cache_entry {
struct pk_cache_entry *next;
u32 keyid[2];
PKT_public_key *pk;
} *pk_cache_entry_t;
static pk_cache_entry_t pk_cache;
static int pk_cache_entries; /* number of entries in pk cache */
static int pk_cache_disabled;
#endif
#if MAX_UID_CACHE_ENTRIES < 5
#error we really need the userid cache
#endif
typedef struct user_id_db {
struct user_id_db *next;
u32 keyid[2];
int len;
char name[1];
} *user_id_db_t;
static user_id_db_t user_id_db;
static int uid_cache_entries; /* number of entries in uid cache */
static int lookup( GETKEY_CTX *ctx, PKT_public_key *pk,
int mode, u32 *keyid, const char *name,
KBNODE *ret_keyblock, int primary );
static void lookup_close( GETKEY_CTX ctx );
static int lookup_read( GETKEY_CTX ctx,
PKT_public_key *pk, KBNODE *ret_keyblock );
static int lookup_sk( PKT_secret_key *sk,
int mode, u32 *keyid, const char *name, int primary );
static void
print_stats()
{
int i;
for(i=0; i < DIM(lkup_stats); i++ ) {
if( lkup_stats[i].any )
fprintf(stderr,
"lookup stats: mode=%-2d ok=%-6d nokey=%-6d err=%-6d\n",
i,
lkup_stats[i].okay_count,
lkup_stats[i].nokey_count,
lkup_stats[i].error_count );
}
}
static void
cache_public_key( PKT_public_key *pk )
{
#if MAX_PK_CACHE_ENTRIES
pk_cache_entry_t ce;
u32 keyid[2];
if( pk_cache_disabled )
return;
if( is_ELGAMAL(pk->pubkey_algo)
|| pk->pubkey_algo == PUBKEY_ALGO_DSA
|| is_RSA(pk->pubkey_algo) ) {
keyid_from_pk( pk, keyid );
}
else
return; /* don't know how to get the keyid */
for( ce = pk_cache; ce; ce = ce->next )
if( ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1] ) {
if( DBG_CACHE )
log_debug("cache_public_key: already in cache\n");
return;
}
if( pk_cache_entries >= MAX_PK_CACHE_ENTRIES ) {
/* fixme: use another algorithm to free some cache slots */
pk_cache_disabled=1;
- if( opt.verbose )
+ if( opt.verbose > 1 )
log_info(_("too many entries in pk cache - disabled\n"));
return;
}
pk_cache_entries++;
ce = m_alloc( sizeof *ce );
ce->next = pk_cache;
pk_cache = ce;
ce->pk = copy_public_key( NULL, pk );
ce->keyid[0] = keyid[0];
ce->keyid[1] = keyid[1];
#endif
}
/****************
* Store the association of keyid and userid
*/
void
cache_user_id( PKT_user_id *uid, u32 *keyid )
{
user_id_db_t r;
for(r=user_id_db; r; r = r->next )
if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) {
if( DBG_CACHE )
log_debug("cache_user_id: already in cache\n");
return;
}
if( uid_cache_entries >= MAX_UID_CACHE_ENTRIES ) {
/* fixme: use another algorithm to free some cache slots */
r = user_id_db;
user_id_db = r->next;
m_free(r);
uid_cache_entries--;
}
r = m_alloc( sizeof *r + uid->len-1 );
r->keyid[0] = keyid[0];
r->keyid[1] = keyid[1];
r->len = uid->len;
memcpy(r->name, uid->name, r->len);
r->next = user_id_db;
user_id_db = r;
uid_cache_entries++;
}
+void
+getkey_disable_caches()
+{
+ #if MAX_UNK_CACHE_ENTRIES
+ {
+ keyid_list_t kl, kl2;
+ for( kl = unknown_keyids; kl; kl = kl2 ) {
+ kl2 = kl->next;
+ m_free(kl);
+ }
+ unknown_keyids = NULL;
+ unk_cache_disabled = 1;
+ }
+ #endif
+ #if MAX_PK_CACHE_ENTRIES
+ {
+ pk_cache_entry_t ce, ce2;
+ u32 keyid[2];
+
+ for( ce = pk_cache; ce; ce = ce2 ) {
+ ce2 = ce->next;
+ free_public_key( ce->pk );
+ m_free( ce );
+ }
+ pk_cache_disabled=1;
+ pk_cache_entries = 0;
+ pk_cache = NULL;
+ }
+ #endif
+ /* fixme: disable user id cache ? */
+}
+
/****************
* Get a public key and store it into the allocated pk
* can be called with PK set to NULL to just read it into some
* internal structures.
*/
int
get_pubkey( PKT_public_key *pk, u32 *keyid )
{
int internal = 0;
int rc = 0;
#if MAX_UNK_CACHE_ENTRIES
{ /* let's see whether we checked the keyid already */
keyid_list_t kl;
for( kl = unknown_keyids; kl; kl = kl->next )
if( kl->keyid[0] == keyid[0] && kl->keyid[1] == keyid[1] )
return G10ERR_NO_PUBKEY; /* already checked and not found */
}
#endif
#if MAX_PK_CACHE_ENTRIES
{ /* Try to get it from the cache */
pk_cache_entry_t ce;
for( ce = pk_cache; ce; ce = ce->next ) {
if( ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1] ) {
if( pk )
copy_public_key( pk, ce->pk );
return 0;
}
}
}
#endif
/* more init stuff */
if( !pk ) {
pk = m_alloc_clear( sizeof *pk );
internal++;
}
/* do a lookup */
rc = lookup( NULL, pk, 11, keyid, NULL, NULL, 0 );
if( !rc )
goto leave;
#if MAX_UNK_CACHE_ENTRIES
/* not found: store it for future reference */
if( unk_cache_disabled )
;
else if( ++unk_cache_entries > MAX_UNK_CACHE_ENTRIES ) {
unk_cache_disabled = 1;
- if( opt.verbose )
+ if( opt.verbose > 1 )
log_info(_("too many entries in unk cache - disabled\n"));
}
else {
keyid_list_t kl;
kl = m_alloc( sizeof *kl );
kl->keyid[0] = keyid[0];
kl->keyid[1] = keyid[1];
kl->next = unknown_keyids;
unknown_keyids = kl;
}
#endif
rc = G10ERR_NO_PUBKEY;
leave:
if( !rc )
cache_public_key( pk );
if( internal )
free_public_key(pk);
return rc;
}
static int
hextobyte( const byte *s )
{
int c;
if( *s >= '0' && *s <= '9' )
c = 16 * (*s - '0');
else if( *s >= 'A' && *s <= 'F' )
c = 16 * (10 + *s - 'A');
else if( *s >= 'a' && *s <= 'f' )
c = 16 * (10 + *s - 'a');
else
return -1;
s++;
if( *s >= '0' && *s <= '9' )
c += *s - '0';
else if( *s >= 'A' && *s <= 'F' )
c += 10 + *s - 'A';
else if( *s >= 'a' && *s <= 'f' )
c += 10 + *s - 'a';
else
return -1;
return c;
}
/****************
* Return the type of the user id:
*
* 0 = Invalid user ID
* 1 = exact match
* 2 = match a substring
* 3 = match an email address
* 4 = match a substring of an email address
* 5 = match an email address, but compare from end
* 10 = it is a short KEYID (don't care about keyid[0])
* 11 = it is a long KEYID
* 16 = it is a 16 byte fingerprint
* 20 = it is a 20 byte fingerprint
*
* if fprint is not NULL, it should be an array of at least 20 bytes.
*
* Rules used:
* - If the username starts with 8,9,16 or 17 hex-digits (the first one
* must be in the range 0..9), this is considered a keyid; depending
* on the length a short or complete one.
* - If the username starts with 32,33,40 or 41 hex-digits (the first one
* must be in the range 0..9), this is considered a fingerprint.
* - If the username starts with a left angle, we assume it is a complete
* email address and look only at this part.
* - If the username starts with a '.', we assume it is the ending
* part of an email address
* - If the username starts with an '@', we assume it is a part of an
* email address
* - If the userid start with an '=' an exact compare is done.
* - If the userid starts with a '*' a case insensitive substring search is
* done (This is the default).
*/
int
classify_user_id( const char *name, u32 *keyid, byte *fprint,
const char **retstr, size_t *retlen )
{
const char *s;
int mode = 0;
/* check what kind of name it is */
for(s = name; *s && isspace(*s); s++ )
;
if( isdigit( *s ) ) { /* a keyid or a fingerprint */
int i, j;
char buf[9];
if( *s == '0' && s[1] == 'x' && isxdigit(s[2]) )
s += 2; /*kludge to allow 0x034343434 */
for(i=0; isxdigit(s[i]); i++ )
;
if( s[i] && !isspace(s[i]) ) /* not terminated by EOS or blank*/
return 0;
else if( i == 8 || (i == 9 && *s == '0') ) { /* short keyid */
if( i==9 )
s++;
if( keyid ) {
keyid[0] = 0;
keyid[1] = strtoul( s, NULL, 16 );
}
mode = 10;
}
else if( i == 16 || (i == 17 && *s == '0') ) { /* complete keyid */
if( i==17 )
s++;
mem2str(buf, s, 9 );
keyid[0] = strtoul( buf, NULL, 16 );
keyid[1] = strtoul( s+8, NULL, 16 );
mode = 11;
}
else if( i == 32 || ( i == 33 && *s == '0' ) ) { /* md5 fingerprint */
if( i==33 )
s++;
if( fprint ) {
memset(fprint+16, 4, 0);
for(j=0; j < 16; j++, s+=2 ) {
int c = hextobyte( s );
if( c == -1 )
return 0;
fprint[j] = c;
}
}
mode = 16;
}
else if( i == 40 || ( i == 41 && *s == '0' ) ) { /* sha1/rmd160 fprint*/
if( i==33 )
s++;
if( fprint ) {
for(j=0; j < 20; j++, s+=2 ) {
int c = hextobyte( s );
if( c == -1 )
return 0;
fprint[j] = c;
}
}
mode = 20;
}
else
return 0;
}
else if( *s == '=' ) { /* exact search */
mode = 1;
s++;
}
else if( *s == '*' ) { /* substring search */
mode = 2;
s++;
}
else if( *s == '<' ) { /* an email address */
mode = 3;
}
else if( *s == '@' ) { /* a part of an email address */
mode = 4;
s++;
}
else if( *s == '.' ) { /* an email address, compare from end */
mode = 5;
s++;
}
else if( *s == '#' ) { /* use local id */
return 0;
}
else if( !*s ) /* empty string */
return 0;
else
mode = 2;
if( retstr )
*retstr = s;
if( retlen )
*retlen = strlen(s);
return mode;
}
/****************
* Try to get the pubkey by the userid. This function looks for the
* first pubkey certificate which has the given name in a user_id.
* if pk has the pubkey algo set, the function will only return
* a pubkey with that algo.
*/
static int
key_byname( int secret, GETKEY_CTX *retctx,
PKT_public_key *pk, PKT_secret_key *sk,
const char *name, KBNODE *ret_kb )
{
int internal = 0;
int rc = 0;
const char *s;
u32 keyid[2] = {0}; /* init to avoid compiler warning */
byte fprint[20];
int mode;
mode = classify_user_id( name, keyid, fprint, &s, NULL );
if( !mode ) {
rc = G10ERR_INV_USER_ID;
goto leave;
}
if( secret ) {
if( !sk ) {
sk = m_alloc_clear( sizeof *sk );
internal++;
}
rc = mode < 16? lookup_sk( sk, mode, keyid, s, 1 )
: lookup_sk( sk, mode, keyid, fprint, 1 );
}
else {
if( !pk ) {
pk = m_alloc_clear( sizeof *pk );
internal++;
}
rc = mode < 16? lookup( retctx, pk, mode, keyid, s, ret_kb, 1 )
: lookup( retctx, pk, mode, keyid, fprint, ret_kb, 1 );
}
leave:
if( internal && secret )
m_free( sk );
else if( internal )
m_free( pk );
return rc;
}
int
get_pubkey_byname( GETKEY_CTX *retctx, PKT_public_key *pk,
const char *name, KBNODE *ret_keyblock )
{
int rc;
if( !pk ) {
/* fixme: key_byname should not need a pk in this case */
pk = m_alloc_clear( sizeof *pk );
rc = key_byname( 0, retctx, pk, NULL, name, ret_keyblock );
free_public_key( pk );
}
else
rc = key_byname( 0, retctx, pk, NULL, name, ret_keyblock );
return rc;
}
int
get_pubkey_next( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock )
{
int rc;
if( !pk ) {
/* fixme: lookup_read should not need a pk in this case */
pk = m_alloc_clear( sizeof *pk );
rc = lookup_read( ctx, pk, ret_keyblock );
free_public_key( pk );
}
else
rc = lookup_read( ctx, pk, ret_keyblock );
return rc;
}
void
get_pubkey_end( GETKEY_CTX ctx )
{
if( ctx ) {
lookup_close( ctx );
m_free( ctx );
}
}
/****************
* Search for a key with the given fingerprint.
*/
int
get_pubkey_byfprint( PKT_public_key *pk, const byte *fprint, size_t fprint_len)
{
int rc;
if( fprint_len == 20 || fprint_len == 16 )
rc = lookup( NULL, pk, fprint_len, NULL, fprint, NULL, 0 );
else
rc = G10ERR_GENERAL; /* Oops */
return rc;
}
/****************
* Search for a key with the given fingerprint and return the
* complete keyblock which may have more than only this key.
*/
int
get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint,
size_t fprint_len )
{
int rc;
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
if( fprint_len == 20 || fprint_len == 16 )
rc = lookup( NULL, pk, fprint_len, NULL, fprint, ret_keyblock, 0 );
else
rc = G10ERR_GENERAL; /* Oops */
free_public_key( pk );
return rc;
}
/****************
* Get a secret key and store it into sk
*/
int
get_seckey( PKT_secret_key *sk, u32 *keyid )
{
int rc;
rc = lookup_sk( sk, 11, keyid, NULL, 0 );
if( !rc ) {
/* check the secret key (this may prompt for a passprase to
* unlock the secret key
*/
rc = check_secret_key( sk, 0 );
}
return rc;
}
/****************
* Check whether the secret key is available
* Returns: 0 := key is available
* G10ERR_NO_SECKEY := not availabe
*/
int
seckey_available( u32 *keyid )
{
PKT_secret_key *sk;
int rc;
sk = m_alloc_clear( sizeof *sk );
rc = lookup_sk( sk, 11, keyid, NULL, 0 );
free_secret_key( sk );
return rc;
}
/****************
* Get a secret key by name and store it into sk
* If NAME is NULL use the default key
*/
int
get_seckey_byname( PKT_secret_key *sk, const char *name, int unprotect )
{
int rc;
if( !name && opt.def_secret_key && *opt.def_secret_key )
rc = key_byname( 1, NULL, NULL, sk, opt.def_secret_key, NULL );
else if( !name ) /* use the first one as default key */
rc = lookup_sk( sk, 15, NULL, NULL, 1 );
else
rc = key_byname( 1, NULL, NULL, sk, name, NULL );
if( !rc && unprotect )
rc = check_secret_key( sk, 0 );
return rc;
}
static int
compare_name( const char *uid, size_t uidlen, const char *name, int mode )
{
int i;
const char *s, *se;
if( mode == 1 ) { /* exact match */
for(i=0; name[i] && uidlen; i++, uidlen-- )
if( uid[i] != name[i] )
break;
if( !uidlen && !name[i] )
return 0; /* found */
}
else if( mode == 2 ) { /* case insensitive substring */
if( memistr( uid, uidlen, name ) )
return 0;
}
else if( mode >= 3 && mode <= 5 ) { /* look at the email address */
for( i=0, s= uid; i < uidlen && *s != '<'; s++, i++ )
;
if( i < uidlen ) {
/* skip opening delim and one char and look for the closing one*/
s++; i++;
for( se=s+1, i++; i < uidlen && *se != '>'; se++, i++ )
;
if( i < uidlen ) {
i = se - s;
if( mode == 3 ) { /* exact email address */
if( strlen(name)-2 == i && !memicmp( s, name+1, i) )
return 0;
}
else if( mode == 4 ) { /* email substring */
if( memistr( s, i, name ) )
return 0;
}
else { /* email from end */
/* nyi */
}
}
}
}
else
BUG();
return -1; /* not found */
}
/****************
* Assume that knode points to a public key packet and keyblock is
* the entire keyblock. This function adds all relevant information from
* a selfsignature to the public key.
*/
static void
merge_one_pk_and_selfsig( KBNODE keyblock, KBNODE knode )
{
PKT_public_key *pk = knode->pkt->pkt.public_key;
PKT_signature *sig;
KBNODE k;
u32 kid[2];
u32 sigdate = 0;
assert( knode->pkt->pkttype == PKT_PUBLIC_KEY
|| knode->pkt->pkttype == PKT_PUBLIC_SUBKEY );
if( pk->version < 4 )
return; /* this is only needed for version >=4 packets */
/* find the selfsignature */
if( knode->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
k = find_kbnode( keyblock, PKT_PUBLIC_KEY );
if( !k )
BUG(); /* keyblock without primary key!!! */
keyid_from_pk( knode->pkt->pkt.public_key, kid );
}
else
keyid_from_pk( pk, kid );
for(k=keyblock; k; k = k->next ) {
if( k->pkt->pkttype == PKT_SIGNATURE
&& (sig=k->pkt->pkt.signature)->sig_class >= 0x10
&& sig->sig_class <= 0x30
&& sig->keyid[0] == kid[0]
&& sig->keyid[1] == kid[1]
&& sig->version > 3 ) {
/* okay this is a self-signature which can be used.
* We use the latest self-signature.
* FIXME: We should only use this if the signature is valid
* but this is time consuming - we must provide another
* way to handle this
*/
const byte *p;
u32 ed;
p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL );
ed = p? pk->timestamp + buffer_to_u32(p):0;
if( sig->timestamp > sigdate ) {
pk->expiredate = ed;
sigdate = sig->timestamp;
}
/* fixme: add usage etc. to pk */
}
}
}
/****************
* merge all selfsignatures with the keys.
*/
void
merge_keys_and_selfsig( KBNODE keyblock )
{
PKT_public_key *pk = NULL;
PKT_secret_key *sk = NULL;
PKT_signature *sig;
KBNODE k;
u32 kid[2] = { 0, 0 };
u32 sigdate = 0;
for(k=keyblock; k; k = k->next ) {
if( k->pkt->pkttype == PKT_PUBLIC_KEY
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
pk = k->pkt->pkt.public_key; sk = NULL;
if( pk->version < 4 )
pk = NULL; /* not needed for old keys */
else if( k->pkt->pkttype == PKT_PUBLIC_KEY )
keyid_from_pk( pk, kid );
}
else if( k->pkt->pkttype == PKT_SECRET_KEY
|| k->pkt->pkttype == PKT_SECRET_SUBKEY ) {
pk = NULL; sk = k->pkt->pkt.secret_key;
if( sk->version < 4 )
sk = NULL;
else if( k->pkt->pkttype == PKT_SECRET_KEY )
keyid_from_sk( sk, kid );
}
else if( (pk || sk ) && k->pkt->pkttype == PKT_SIGNATURE
&& (sig=k->pkt->pkt.signature)->sig_class >= 0x10
&& sig->sig_class <= 0x30 && sig->version > 3
&& sig->keyid[0] == kid[0] && sig->keyid[1] == kid[1] ) {
/* okay this is a self-signature which can be used.
* FIXME: We should only use this if the signature is valid
* but this is time consuming - we must provide another
* way to handle this
*/
const byte *p;
u32 ed;
p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_KEY_EXPIRE, NULL );
if( pk ) {
ed = p? pk->timestamp + buffer_to_u32(p):0;
if( sig->timestamp > sigdate ) {
pk->expiredate = ed;
sigdate = sig->timestamp;
}
}
else {
ed = p? sk->timestamp + buffer_to_u32(p):0;
if( sig->timestamp > sigdate ) {
sk->expiredate = ed;
sigdate = sig->timestamp;
}
}
}
}
}
static KBNODE
find_by_name( KBNODE keyblock, PKT_public_key *pk, const char *name,
int mode, byte *namehash, int *use_namehash )
{
KBNODE k, kk;
for(k=keyblock; k; k = k->next ) {
if( k->pkt->pkttype == PKT_USER_ID
&& !compare_name( k->pkt->pkt.user_id->name,
k->pkt->pkt.user_id->len, name, mode)) {
/* we found a matching name, look for the key */
for(kk=keyblock; kk; kk = kk->next ) {
if( ( kk->pkt->pkttype == PKT_PUBLIC_KEY
|| kk->pkt->pkttype == PKT_PUBLIC_SUBKEY )
&& ( !pk->pubkey_algo
|| pk->pubkey_algo
== kk->pkt->pkt.public_key->pubkey_algo)
&& ( !pk->pubkey_usage
|| !check_pubkey_algo2(
kk->pkt->pkt.public_key->pubkey_algo,
pk->pubkey_usage ))
)
break;
}
if( kk ) {
u32 aki[2];
keyid_from_pk( kk->pkt->pkt.public_key, aki );
cache_user_id( k->pkt->pkt.user_id, aki );
rmd160_hash_buffer( namehash,
k->pkt->pkt.user_id->name,
k->pkt->pkt.user_id->len );
*use_namehash = 1;
return kk;
}
else if( is_RSA(pk->pubkey_algo) )
log_error("RSA key cannot be used in this version\n");
else
log_error("No key for userid\n");
}
}
return NULL;
}
static KBNODE
find_by_keyid( KBNODE keyblock, PKT_public_key *pk, u32 *keyid, int mode )
{
KBNODE k;
if( DBG_CACHE )
log_debug("lookup keyid=%08lx%08lx req_algo=%d mode=%d\n",
(ulong)keyid[0], (ulong)keyid[1], pk->pubkey_algo, mode );
for(k=keyblock; k; k = k->next ) {
if( k->pkt->pkttype == PKT_PUBLIC_KEY
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
u32 aki[2];
keyid_from_pk( k->pkt->pkt.public_key, aki );
if( DBG_CACHE )
log_debug(" aki=%08lx%08lx algo=%d\n",
(ulong)aki[0], (ulong)aki[1],
k->pkt->pkt.public_key->pubkey_algo );
if( aki[1] == keyid[1]
&& ( mode == 10 || aki[0] == keyid[0] )
&& ( !pk->pubkey_algo
|| pk->pubkey_algo
== k->pkt->pkt.public_key->pubkey_algo) ){
KBNODE kk;
/* cache the userid */
for(kk=keyblock; kk; kk = kk->next )
if( kk->pkt->pkttype == PKT_USER_ID )
break;
if( kk )
cache_user_id( kk->pkt->pkt.user_id, aki );
else
log_error("No userid for key\n");
return k; /* found */
}
}
}
return NULL;
}
static KBNODE
find_first( KBNODE keyblock, PKT_public_key *pk )
{
KBNODE k;
for(k=keyblock; k; k = k->next ) {
if( k->pkt->pkttype == PKT_PUBLIC_KEY
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY )
{
if( !pk->pubkey_algo
|| pk->pubkey_algo == k->pkt->pkt.public_key->pubkey_algo )
return k;
}
}
return NULL;
}
static KBNODE
find_by_fpr( KBNODE keyblock, PKT_public_key *pk, const char *name, int mode )
{
KBNODE k;
for(k=keyblock; k; k = k->next ) {
if( k->pkt->pkttype == PKT_PUBLIC_KEY
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
byte afp[MAX_FINGERPRINT_LEN];
size_t an;
fingerprint_from_pk(k->pkt->pkt.public_key, afp, &an );
if( DBG_CACHE ) {
u32 aki[2];
keyid_from_pk( k->pkt->pkt.public_key, aki );
log_debug(" aki=%08lx%08lx algo=%d mode=%d an=%u\n",
(ulong)aki[0], (ulong)aki[1],
k->pkt->pkt.public_key->pubkey_algo, mode, an );
}
if( an == mode
&& !memcmp( afp, name, an)
&& ( !pk->pubkey_algo
|| pk->pubkey_algo == k->pkt->pkt.public_key->pubkey_algo) )
return k;
}
}
return NULL;
}
static void
finish_lookup( KBNODE keyblock, PKT_public_key *pk, KBNODE k, byte *namehash,
int use_namehash, int primary )
{
assert( k->pkt->pkttype == PKT_PUBLIC_KEY
|| k->pkt->pkttype == PKT_PUBLIC_SUBKEY );
assert( keyblock->pkt->pkttype == PKT_PUBLIC_KEY );
if( primary && !pk->pubkey_usage ) {
copy_public_key_new_namehash( pk, keyblock->pkt->pkt.public_key,
use_namehash? namehash:NULL);
merge_one_pk_and_selfsig( keyblock, keyblock );
}
else {
if( primary && pk->pubkey_usage
&& check_pubkey_algo2( k->pkt->pkt.public_key->pubkey_algo,
pk->pubkey_usage ) == G10ERR_WR_PUBKEY_ALGO ) {
/* if the usage is not correct, try to use a subkey */
KBNODE save_k = k;
k = NULL;
/* kludge for pgp 5: which doesn't accept type 20:
* try to use a type 16 subkey instead */
if( pk->pubkey_usage == PUBKEY_USAGE_ENC ) {
for( k = save_k; k; k = k->next ) {
if( k->pkt->pkttype == PKT_PUBLIC_SUBKEY
&& k->pkt->pkt.public_key->pubkey_algo
== PUBKEY_ALGO_ELGAMAL_E
&& !check_pubkey_algo2(
k->pkt->pkt.public_key->pubkey_algo,
pk->pubkey_usage ) )
break;
}
}
if( !k ) {
for(k = save_k ; k; k = k->next ) {
if( k->pkt->pkttype == PKT_PUBLIC_SUBKEY
&& !check_pubkey_algo2(
k->pkt->pkt.public_key->pubkey_algo,
pk->pubkey_usage ) )
break;
}
}
if( !k )
k = save_k;
else
log_info(_("using secondary key %08lX "
"instead of primary key %08lX\n"),
(ulong)keyid_from_pk( k->pkt->pkt.public_key, NULL),
(ulong)keyid_from_pk( save_k->pkt->pkt.public_key, NULL)
);
}
copy_public_key_new_namehash( pk, k->pkt->pkt.public_key,
use_namehash? namehash:NULL);
merge_one_pk_and_selfsig( keyblock, k );
}
}
/****************
* Lookup a key by scanning all keyresources
* mode 1 = lookup by NAME (exact)
* 2 = lookup by NAME (substring)
* 3 = lookup by NAME (email address)
* 4 = email address (substring)
* 5 = email address (compare from end)
* 10 = lookup by short KEYID (don't care about keyid[0])
* 11 = lookup by long KEYID
* 15 = Get the first key.
* 16 = lookup by 16 byte fingerprint which is stored in NAME
* 20 = lookup by 20 byte fingerprint which is stored in NAME
* Caller must provide an empty PK, if the pubkey_algo is filled in, only
* a key of this algo will be returned.
* If ret_keyblock is not NULL, the complete keyblock is returned also
* and the caller must release it.
*/
static int
lookup( GETKEY_CTX *retctx, PKT_public_key *pk, int mode, u32 *keyid,
const char *name, KBNODE *ret_keyblock, int primary )
{
struct getkey_ctx_s help_ctx;
GETKEY_CTX ctx;
int rc;
if( !retctx )
ctx = &help_ctx;
else {
ctx = m_alloc( sizeof *ctx );
*retctx = ctx;
}
memset( ctx, 0, sizeof *ctx );
ctx->mode = mode;
if( keyid ) {
ctx->keyid[0] = keyid[0];
ctx->keyid[1] = keyid[1];
}
if( retctx ) {
ctx->namebuf = name? m_strdup(name) : NULL;
ctx->name = ctx->namebuf;
}
else
ctx->name = name;
ctx->primary = primary;
rc = lookup_read( ctx, pk, ret_keyblock );
if( !retctx )
lookup_close( ctx );
return rc;
}
static void
lookup_close( GETKEY_CTX ctx )
{
enum_keyblocks( 2, &ctx->kbpos, NULL ); /* close */
m_free( ctx->namebuf );
}
static int
lookup_read( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock )
{
int rc;
KBNODE k;
int oldmode = set_packet_list_mode(0);
byte namehash[20];
int use_namehash=0;
/* try the quick functions */
if( !ctx->count ) {
k = NULL;
switch( ctx->mode ) {
case 10:
case 11:
rc = locate_keyblock_by_keyid( &ctx->kbpos, ctx->keyid,
ctx->mode==10, 0 );
if( !rc )
rc = read_keyblock( &ctx->kbpos, &ctx->keyblock );
if( !rc )
k = find_by_keyid( ctx->keyblock, pk, ctx->keyid, ctx->mode );
break;
case 16:
case 20:
rc = locate_keyblock_by_fpr( &ctx->kbpos, ctx->name, ctx->mode, 0 );
if( !rc )
rc = read_keyblock( &ctx->kbpos, &ctx->keyblock );
if( !rc )
k = find_by_fpr( ctx->keyblock, pk, ctx->name, ctx->mode );
break;
default: rc = G10ERR_UNSUPPORTED;
}
if( !rc ) {
if( !k ) {
log_error("lookup: key has been located but was not found\n");
rc = G10ERR_INV_KEYRING;
}
else
finish_lookup( ctx->keyblock, pk, k, namehash, 0, ctx->primary );
}
}
else
rc = G10ERR_UNSUPPORTED;
/* if this was not possible, loop over all keyblocks
* fixme: If one of the resources in the quick functions above
* works, but the key was not found, we will not find it
* in the other resources */
if( rc == G10ERR_UNSUPPORTED ) {
if( !ctx->count )
rc = enum_keyblocks( 0, &ctx->kbpos, &ctx->keyblock );
else
rc = 0;
if( !rc ) {
while( !(rc = enum_keyblocks( 1, &ctx->kbpos, &ctx->keyblock )) ) {
/* fixme: we don´t enum the complete keyblock, but
* use the first match and that continue with the next keyblock
*/
if( ctx->mode < 10 )
k = find_by_name( ctx->keyblock, pk, ctx->name, ctx->mode,
namehash, &use_namehash);
else if( ctx->mode == 10 ||ctx-> mode == 11 )
k = find_by_keyid( ctx->keyblock, pk, ctx->keyid,
ctx->mode );
else if( ctx->mode == 15 )
k = find_first( ctx->keyblock, pk );
else if( ctx->mode == 16 || ctx->mode == 20 )
k = find_by_fpr( ctx->keyblock, pk, ctx->name, ctx->mode );
else
BUG();
if( k ) {
finish_lookup( ctx->keyblock, pk, k, namehash,
use_namehash, ctx->primary );
break; /* found */
}
release_kbnode( ctx->keyblock );
ctx->keyblock = NULL;
}
}
if( rc && rc != -1 )
log_error("enum_keyblocks failed: %s\n", g10_errstr(rc));
}
if( !rc ) {
if( ret_keyblock ) {
*ret_keyblock = ctx->keyblock;
ctx->keyblock = NULL;
}
}
else if( rc == -1 )
rc = G10ERR_NO_PUBKEY;
release_kbnode( ctx->keyblock );
ctx->keyblock = NULL;
set_packet_list_mode(oldmode);
if( opt.debug & DBG_MEMSTAT_VALUE ) {
static int initialized;
if( !initialized ) {
initialized = 1;
atexit( print_stats );
}
assert( ctx->mode < DIM(lkup_stats) );
lkup_stats[ctx->mode].any = 1;
if( !rc )
lkup_stats[ctx->mode].okay_count++;
else if ( rc == G10ERR_NO_PUBKEY )
lkup_stats[ctx->mode].nokey_count++;
else
lkup_stats[ctx->mode].error_count++;
}
ctx->last_rc = rc;
ctx->count++;
return rc;
}
/****************
* Ditto for secret keys
*/
static int
lookup_sk( PKT_secret_key *sk, int mode, u32 *keyid, const char *name,
int primary )
{
int rc;
KBNODE keyblock = NULL;
KBPOS kbpos;
int oldmode = set_packet_list_mode(0);
rc = enum_keyblocks( 5 /* open secret */, &kbpos, &keyblock );
if( rc ) {
if( rc == -1 )
rc = G10ERR_NO_SECKEY;
else if( rc )
log_error("enum_keyblocks(open secret) failed: %s\n", g10_errstr(rc) );
goto leave;
}
while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) {
KBNODE k, kk;
if( mode < 10 ) { /* name lookup */
for(k=keyblock; k; k = k->next ) {
if( k->pkt->pkttype == PKT_USER_ID
&& !compare_name( k->pkt->pkt.user_id->name,
k->pkt->pkt.user_id->len, name, mode)) {
/* we found a matching name, look for the key */
for(kk=keyblock; kk; kk = kk->next ) {
if( ( kk->pkt->pkttype == PKT_SECRET_KEY
|| kk->pkt->pkttype == PKT_SECRET_SUBKEY )
&& ( !sk->pubkey_algo
|| sk->pubkey_algo
== kk->pkt->pkt.secret_key->pubkey_algo)
&& ( !sk->pubkey_usage
|| !check_pubkey_algo2(
kk->pkt->pkt.secret_key->pubkey_algo,
sk->pubkey_usage ))
)
break;
}
if( kk ) {
u32 aki[2];
keyid_from_sk( kk->pkt->pkt.secret_key, aki );
cache_user_id( k->pkt->pkt.user_id, aki );
k = kk;
break;
}
else
log_error("No key for userid (in sk)\n");
}
}
}
else { /* keyid or fingerprint lookup */
if( DBG_CACHE && (mode== 10 || mode==11) ) {
log_debug("lookup_sk keyid=%08lx%08lx req_algo=%d mode=%d\n",
(ulong)keyid[0], (ulong)keyid[1],
sk->pubkey_algo, mode );
}
for(k=keyblock; k; k = k->next ) {
if( k->pkt->pkttype == PKT_SECRET_KEY
|| k->pkt->pkttype == PKT_SECRET_SUBKEY ) {
if( mode == 10 || mode == 11 ) {
u32 aki[2];
keyid_from_sk( k->pkt->pkt.secret_key, aki );
if( DBG_CACHE ) {
log_debug(" aki=%08lx%08lx algo=%d\n",
(ulong)aki[0], (ulong)aki[1],
k->pkt->pkt.secret_key->pubkey_algo );
}
if( aki[1] == keyid[1]
&& ( mode == 10 || aki[0] == keyid[0] )
&& ( !sk->pubkey_algo
|| sk->pubkey_algo
== k->pkt->pkt.secret_key->pubkey_algo) ){
/* cache the userid */
for(kk=keyblock; kk; kk = kk->next )
if( kk->pkt->pkttype == PKT_USER_ID )
break;
if( kk )
cache_user_id( kk->pkt->pkt.user_id, aki );
else
log_error("No userid for key\n");
break; /* found */
}
}
else if( mode == 15 ) { /* get the first key */
if( !sk->pubkey_algo
|| sk->pubkey_algo
== k->pkt->pkt.secret_key->pubkey_algo )
break;
}
else if( mode == 16 || mode == 20 ) {
size_t an;
byte afp[MAX_FINGERPRINT_LEN];
fingerprint_from_sk(k->pkt->pkt.secret_key, afp, &an );
if( an == mode && !memcmp( afp, name, an)
&& ( !sk->pubkey_algo
|| sk->pubkey_algo
== k->pkt->pkt.secret_key->pubkey_algo) ) {
break;
}
}
else
BUG();
} /* end compare secret keys */
}
}
if( k ) { /* found */
assert( k->pkt->pkttype == PKT_SECRET_KEY
|| k->pkt->pkttype == PKT_SECRET_SUBKEY );
assert( keyblock->pkt->pkttype == PKT_SECRET_KEY );
if( primary && !sk->pubkey_usage )
copy_secret_key( sk, keyblock->pkt->pkt.secret_key );
else
copy_secret_key( sk, k->pkt->pkt.secret_key );
break; /* enumeration */
}
release_kbnode( keyblock );
keyblock = NULL;
}
if( rc == -1 )
rc = G10ERR_NO_SECKEY;
else if( rc )
log_error("enum_keyblocks(read) failed: %s\n", g10_errstr(rc));
leave:
enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
release_kbnode( keyblock );
set_packet_list_mode(oldmode);
return rc;
}
/****************
* Enumerate all primary secret keys. Caller must use these procedure:
* 1) create a void pointer and initialize it to NULL
* 2) pass this void pointer by reference to this function
* and provide space for the secret key (pass a buffer for sk)
* 3) call this function as long as it does not return -1
* to indicate EOF.
* 4) Always call this function a last time with SK set to NULL,
* so that can free it's context.
*
*
*/
int
enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys )
{
int rc=0;
PACKET pkt;
int save_mode;
struct {
int eof;
int sequence;
const char *name;
IOBUF iobuf;
} *c = *context;
if( !c ) { /* make a new context */
c = m_alloc_clear( sizeof *c );
*context = c;
c->sequence = 0;
c->name = enum_keyblock_resources( &c->sequence, 1 );
}
if( !sk ) { /* free the context */
if( c->iobuf )
iobuf_close(c->iobuf);
m_free( c );
*context = NULL;
return 0;
}
if( c->eof )
return -1;
/* FIXME: This assumes a plain keyring file */
for( ; c->name; c->name = enum_keyblock_resources( &c->sequence, 1 ) ) {
if( !c->iobuf ) {
if( !(c->iobuf = iobuf_open( c->name ) ) ) {
log_error("enum_secret_keys: can't open '%s'\n", c->name );
continue; /* try next file */
}
}
save_mode = set_packet_list_mode(0);
init_packet(&pkt);
while( (rc=parse_packet(c->iobuf, &pkt)) != -1 ) {
if( rc )
; /* e.g. unknown packet */
else if( pkt.pkttype == PKT_SECRET_KEY
|| ( with_subkeys && pkt.pkttype == PKT_SECRET_SUBKEY ) ) {
copy_secret_key( sk, pkt.pkt.secret_key );
set_packet_list_mode(save_mode);
return 0; /* found */
}
free_packet(&pkt);
}
set_packet_list_mode(save_mode);
iobuf_close(c->iobuf); c->iobuf = NULL;
}
c->eof = 1;
return -1;
}
/****************
* Return a string with a printable representation of the user_id.
* this string must be freed by m_free.
*/
char*
get_user_id_string( u32 *keyid )
{
user_id_db_t r;
char *p;
int pass=0;
/* try it two times; second pass reads from key resources */
do {
for(r=user_id_db; r; r = r->next )
if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) {
p = m_alloc( r->len + 10 );
sprintf(p, "%08lX %.*s", (ulong)keyid[1], r->len, r->name );
return p;
}
} while( ++pass < 2 && !get_pubkey( NULL, keyid ) );
p = m_alloc( 15 );
sprintf(p, "%08lX [?]", (ulong)keyid[1] );
return p;
}
char*
get_long_user_id_string( u32 *keyid )
{
user_id_db_t r;
char *p;
int pass=0;
/* try it two times; second pass reads from key resources */
do {
for(r=user_id_db; r; r = r->next )
if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) {
p = m_alloc( r->len + 20 );
sprintf(p, "%08lX%08lX %.*s",
(ulong)keyid[0], (ulong)keyid[1], r->len, r->name );
return p;
}
} while( ++pass < 2 && !get_pubkey( NULL, keyid ) );
p = m_alloc( 25 );
sprintf(p, "%08lX%08lX [?]", (ulong)keyid[0], (ulong)keyid[1] );
return p;
}
char*
get_user_id( u32 *keyid, size_t *rn )
{
user_id_db_t r;
char *p;
int pass=0;
/* try it two times; second pass reads from key resources */
do {
for(r=user_id_db; r; r = r->next )
if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) {
p = m_alloc( r->len );
memcpy(p, r->name, r->len );
*rn = r->len;
return p;
}
} while( ++pass < 2 && !get_pubkey( NULL, keyid ) );
p = m_alloc( 19 );
memcpy(p, "[User id not found]", 19 );
*rn = 19;
return p;
}
diff --git a/g10/gpgd.c b/g10/gpgd.c
index 5d85e1f13..b4be6044c 100644
--- a/g10/gpgd.c
+++ b/g10/gpgd.c
@@ -1,309 +1,309 @@
-/* ggpd.c - The GNUPG daemon (keyserver)
+/* ggpd.c - The GnuPG daemon (keyserver)
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 is a spinning server for most purposes, the server does only
* fork for updates (which may require signature checks and lengthy DB
* operations).
*
* see ks-proto.c for the used protocol.
* see ks-db.c for the layout of the database.
*/
#include <config.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "util.h"
#include "cipher.h"
#include "options.h"
#include "main.h"
static ARGPARSE_OPTS opts[] = {
{ 'v', "verbose", 0, "verbose" },
{ 501, "options" ,2, "read options from file"},
{ 502, "no-daemon", 0, "do not operate as a daemon" },
{ 510, "debug" ,4|16, "set debugging flags"},
{ 511, "debug-all" ,0, "enable full debugging"},
{0} };
static char *build_list( const char *text,
const char * (*mapf)(int), int (*chkf)(int) );
static void become_daemon(void);
const char *
strusage( int level )
{
static char *digests, *pubkeys, *ciphers;
const char *p;
switch( level ) {
case 11: p = "gpgd (GNUPG)"; break;
case 13: p = VERSION; break;
case 17: p = PRINTABLE_OS_NAME; break;
case 19: p =
"Please report bugs to <gnupg-bugs@gnu.org>.\n";
break;
case 1:
case 40: p = "Usage: gpgd [options] (-h for help)";
break;
case 41: p = "Syntax: gpgd [options] [files]\n"
"GNUPG keyserver\n";
break;
case 31: p = "\n"; break;
case 32:
if( !ciphers )
ciphers = build_list("Supported ciphers: ", cipher_algo_to_string,
check_cipher_algo );
p = ciphers;
break;
case 33:
if( !pubkeys )
pubkeys = build_list("Supported pubkeys: ", pubkey_algo_to_string,
check_pubkey_algo );
p = pubkeys;
break;
case 34:
if( !digests )
digests = build_list("Supported digests: ", digest_algo_to_string,
check_digest_algo );
p = digests;
break;
default: p = default_strusage(level);
}
return p;
}
static char *
build_list( const char *text, const char * (*mapf)(int), int (*chkf)(int) )
{
int i;
const char *s;
size_t n=strlen(text)+2;
char *list, *p;
for(i=1; i < 100; i++ )
if( !chkf(i) && (s=mapf(i)) )
n += strlen(s) + 2;
list = m_alloc( 21 + n ); *list = 0;
for(p=NULL, i=1; i < 100; i++ ) {
if( !chkf(i) && (s=mapf(i)) ) {
if( !p )
p = stpcpy( list, text );
else
p = stpcpy( p, ", ");
p = stpcpy(p, s );
}
}
if( p )
p = stpcpy(p, "\n" );
return list;
}
static void
set_debug(void)
{
if( opt.debug & DBG_MEMORY_VALUE )
memory_debug_mode = 1;
if( opt.debug & DBG_MEMSTAT_VALUE )
memory_stat_debug_mode = 1;
if( opt.debug & DBG_MPI_VALUE )
mpi_debug_mode = 1;
if( opt.debug & DBG_CIPHER_VALUE )
g10c_debug_mode = 1;
if( opt.debug & DBG_IOBUF_VALUE )
iobuf_debug_mode = 1;
}
int
main( int argc, char **argv )
{
ARGPARSE_ARGS pargs;
int orig_argc;
char **orig_argv;
FILE *configfp = NULL;
char *configname = NULL;
unsigned configlineno;
int parse_debug = 0;
int default_config =1;
int daemon = 1;
secmem_init( 0 ); /* disable use of secmem */
log_set_name("gpgd");
log_set_pid( getpid() );
opt.compress = -1; /* defaults to standard compress level */
opt.batch = 1;
/* check whether we have a config file on the commandline */
orig_argc = argc;
orig_argv = argv;
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1; /* do not remove the args */
while( arg_parse( &pargs, opts) ) {
if( pargs.r_opt == 510 || pargs.r_opt == 511 )
parse_debug++;
else if( pargs.r_opt == 501 ) {
/* yes there is one, so we do not try the default one, but
* read the option file when it is encountered at the commandline
*/
default_config = 0;
}
}
if( default_config )
configname = make_filename("/etc/gpgd.conf", NULL );
argc = orig_argc;
argv = orig_argv;
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags= 1; /* do not remove the args */
next_pass:
if( configname ) {
configlineno = 0;
configfp = fopen( configname, "r" );
if( !configfp ) {
if( default_config ) {
if( parse_debug )
log_info("note: no default option file '%s'\n",
configname );
}
else {
log_error("option file '%s': %s\n",
configname, strerror(errno) );
g10_exit(1);
}
m_free(configname); configname = NULL;
}
if( parse_debug && configname )
log_info("reading options from '%s'\n", configname );
default_config = 0;
}
while( optfile_parse( configfp, configname, &configlineno,
&pargs, opts) ) {
switch( pargs.r_opt ) {
case 'v': opt.verbose++; break;
case 501:
if( !configfp ) {
m_free(configname);
configname = m_strdup(pargs.r.ret_str);
goto next_pass;
}
break;
case 502: daemon = 0; break;
case 510: opt.debug |= pargs.r.ret_ulong; break;
case 511: opt.debug = ~0; break;
default : pargs.err = configfp? 1:2; break;
}
}
if( configfp ) {
fclose( configfp );
configfp = NULL;
m_free(configname); configname = NULL;
goto next_pass;
}
m_free( configname ); configname = NULL;
if( log_get_errorcount(0) )
g10_exit(2);
fprintf(stderr, "%s %s; %s\n", strusage(11), strusage(13), strusage(14) );
fprintf(stderr, "%s\n", strusage(15) );
set_debug();
if( daemon )
become_daemon();
g10_exit(0);
return 8; /*NEVER REACHED*/
}
void
g10_exit( int rc )
{
secmem_term();
rc = rc? rc : log_get_errorcount(0)? 2:0;
exit(rc );
}
static void
become_daemon()
{
long nfile;
int i, n;
int childpid;
if( opt.verbose )
log_info("becoming a daemon ...\n");
fflush(NULL);
/* FIXME: handle the TTY signals */
if( (childpid = fork()) == -1 )
log_fatal("can't fork first child: %s\n", strerror(errno));
else if( childpid > 0 )
exit(0); /* terminate parent */
/* Disassociate from controlling terminal etc. */
if( setsid() == -1 )
log_fatal("setsid() failed: %s\n", strerror(errno) );
log_set_pid( getpid() );
/* close all files but not the log files */
if( (nfile=sysconf( _SC_OPEN_MAX )) < 0 )
#ifdef _POSIX_OPEN_MAX
nfile = _POSIX_OPEN_MAX;
#else
nfile = 20; /* assume a common value */
#endif
n = fileno( stderr );
for(i=0; i < nfile; i++ )
if( i != n )
close(i);
errno = 0;
if( chdir("/") )
log_fatal("chdir to root failed: %s\n", strerror(errno) );
umask(0);
/* do not let possible children become zombies */
signal(SIGCHLD, SIG_IGN);
if( opt.verbose )
log_info("now running as daemon\n");
}
diff --git a/g10/import.c b/g10/import.c
index 2fa25c542..7de0fc919 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -1,1094 +1,1097 @@
/* import.c
* 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
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include "options.h"
#include "packet.h"
#include "errors.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "trustdb.h"
#include "main.h"
#include "i18n.h"
static struct {
ulong no_user_id;
ulong imported;
ulong imported_rsa;
ulong n_uids;
ulong n_sigs;
ulong n_subk;
ulong unchanged;
ulong n_revoc;
ulong secret_read;
ulong secret_imported;
ulong secret_dups;
} stats;
static int read_block( IOBUF a, compress_filter_context_t *cfx,
PACKET **pending_pkt, KBNODE *ret_root );
static int import_one( const char *fname, KBNODE keyblock, int fast );
static int import_secret_one( const char *fname, KBNODE keyblock );
static int import_revoke_cert( const char *fname, KBNODE node );
static int chk_self_sigs( const char *fname, KBNODE keyblock,
PKT_public_key *pk, u32 *keyid );
static int delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid );
static int merge_blocks( const char *fname, KBNODE keyblock_orig,
KBNODE keyblock, u32 *keyid,
int *n_uids, int *n_sigs, int *n_subk );
static int append_uid( KBNODE keyblock, KBNODE node, int *n_sigs,
const char *fname, u32 *keyid );
static int append_key( KBNODE keyblock, KBNODE node, int *n_sigs,
const char *fname, u32 *keyid );
static int merge_sigs( KBNODE dst, KBNODE src, int *n_sigs,
const char *fname, u32 *keyid );
static int merge_keysigs( KBNODE dst, KBNODE src, int *n_sigs,
const char *fname, u32 *keyid );
/****************
* Import the public keys from the given filename. Input may be armored.
* This function rejects all keys which are not validly self signed on at
* least one userid. Only user ids which are self signed will be imported.
* Other signatures are not checked.
*
* Actually this function does a merge. It works like this:
*
* - get the keyblock
* - check self-signatures and remove all userids and their signatures
* without/invalid self-signatures.
* - reject the keyblock, if we have no valid userid.
* - See whether we have this key already in one of our pubrings.
* If not, simply add it to the default keyring.
* - Compare the key and the self-signatures of the new and the one in
* our keyring. If they are different something weird is going on;
* ask what to do.
* - See whether we have only non-self-signature on one user id; if not
* ask the user what to do.
* - compare the signatures: If we already have this signature, check
* that they compare okay; if not, issue a warning and ask the user.
* (consider looking at the timestamp and use the newest?)
* - Simply add the signature. Can't verify here because we may not have
* the signature's public key yet; verification is done when putting it
* into the trustdb, which is done automagically as soon as this pubkey
* is used.
* - Proceed with next signature.
*
* Key revocation certificates have special handling.
*
*/
int
import_keys( const char *fname, int fast )
{
armor_filter_context_t afx;
compress_filter_context_t cfx;
PACKET *pending_pkt = NULL;
IOBUF inp = NULL;
KBNODE keyblock;
int rc = 0;
ulong count=0;
memset( &afx, 0, sizeof afx);
memset( &cfx, 0, sizeof cfx);
afx.only_keyblocks = 1;
/* fixme: don't use static variables */
memset( &stats, 0, sizeof( stats ) );
/* open file */
inp = iobuf_open(fname);
if( !fname )
fname = "[stdin]";
if( !inp ) {
log_error_f(fname, _("can't open file: %s\n"), strerror(errno) );
return G10ERR_OPEN_FILE;
}
+
+ getkey_disable_caches();
+
if( !opt.no_armor ) /* armored reading is not disabled */
iobuf_push_filter( inp, armor_filter, &afx );
while( !(rc = read_block( inp, &cfx, &pending_pkt, &keyblock) )) {
if( keyblock->pkt->pkttype == PKT_PUBLIC_KEY )
rc = import_one( fname, keyblock, fast );
else if( keyblock->pkt->pkttype == PKT_SECRET_KEY )
rc = import_secret_one( fname, keyblock );
else if( keyblock->pkt->pkttype == PKT_SIGNATURE
&& keyblock->pkt->pkt.signature->sig_class == 0x20 )
rc = import_revoke_cert( fname, keyblock );
else {
log_info_f(fname, _("skipping block of type %d\n"),
keyblock->pkt->pkttype );
}
release_kbnode(keyblock);
if( rc )
break;
if( !(++count % 100) )
log_info(_("%lu keys so far processed\n"), count );
}
if( rc == -1 )
rc = 0;
else if( rc && rc != G10ERR_INV_KEYRING )
log_error_f( fname, _("read error: %s\n"), g10_errstr(rc));
log_info(_("Total number processed: %lu\n"), count );
if( stats.no_user_id )
log_info(_(" w/o user IDs: %lu\n"), stats.no_user_id );
if( stats.imported || stats.imported_rsa ) {
log_info(_(" imported: %lu"), stats.imported );
if( stats.imported_rsa )
fprintf(stderr, " (RSA: %lu)", stats.imported_rsa );
putc('\n', stderr);
}
if( stats.unchanged )
log_info(_(" unchanged: %lu\n"), stats.unchanged );
if( stats.n_uids )
log_info(_(" new user IDs: %lu\n"), stats.n_uids );
if( stats.n_subk )
log_info(_(" new subkeys: %lu\n"), stats.n_subk );
if( stats.n_sigs )
log_info(_(" new signatures: %lu\n"), stats.n_sigs );
if( stats.n_revoc )
log_info(_(" new key revocations: %lu\n"), stats.n_revoc );
if( stats.secret_read )
log_info(_(" secret keys read: %lu\n"), stats.secret_read );
if( stats.secret_imported )
log_info(_(" secret keys imported: %lu\n"), stats.secret_imported );
if( stats.secret_dups )
log_info(_(" secret keys unchanged: %lu\n"), stats.secret_dups );
iobuf_close(inp);
return rc;
}
/****************
* Read the next keyblock from stream A, CFX is used to handle
* compressed keyblocks. PENDING_PKT should be initialzed to NULL
* and not chnaged form the caller.
* Retunr: 0 = okay, -1 no more blocks or another errorcode.
*/
static int
read_block( IOBUF a, compress_filter_context_t *cfx,
PACKET **pending_pkt, KBNODE *ret_root )
{
int rc;
PACKET *pkt;
KBNODE root = NULL;
int in_cert;
if( *pending_pkt ) {
root = new_kbnode( *pending_pkt );
*pending_pkt = NULL;
in_cert = 1;
}
else
in_cert = 0;
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
while( (rc=parse_packet(a, pkt)) != -1 ) {
if( rc ) { /* ignore errors */
if( rc != G10ERR_UNKNOWN_PACKET ) {
log_error("read_block: read error: %s\n", g10_errstr(rc) );
rc = G10ERR_INV_KEYRING;
goto ready;
}
free_packet( pkt );
init_packet(pkt);
continue;
}
if( !root && pkt->pkttype == PKT_SIGNATURE
&& pkt->pkt.signature->sig_class == 0x20 ) {
/* this is a revocation certificate which is handled
* in a special way */
root = new_kbnode( pkt );
pkt = NULL;
goto ready;
}
/* make a linked list of all packets */
switch( pkt->pkttype ) {
case PKT_COMPRESSED:
if( pkt->pkt.compressed->algorithm < 1
|| pkt->pkt.compressed->algorithm > 2 ) {
rc = G10ERR_COMPR_ALGO;
goto ready;
}
cfx->algo = pkt->pkt.compressed->algorithm;
pkt->pkt.compressed->buf = NULL;
iobuf_push_filter( a, compress_filter, cfx );
free_packet( pkt );
init_packet(pkt);
break;
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
if( in_cert ) { /* store this packet */
*pending_pkt = pkt;
pkt = NULL;
goto ready;
}
in_cert = 1;
default:
if( in_cert ) {
if( !root )
root = new_kbnode( pkt );
else
add_kbnode( root, new_kbnode( pkt ) );
pkt = m_alloc( sizeof *pkt );
}
init_packet(pkt);
break;
}
}
ready:
if( rc == -1 && root )
rc = 0;
if( rc )
release_kbnode( root );
else
*ret_root = root;
free_packet( pkt );
m_free( pkt );
return rc;
}
/****************
* Try to import one keyblock. Return an error only in serious cases, but
* never for an invalid keyblock. It uses log_error to increase the
* internal errorcount, so that invalid input can be detected by programs
* which called g10.
*/
static int
import_one( const char *fname, KBNODE keyblock, int fast )
{
PKT_public_key *pk;
PKT_public_key *pk_orig;
KBNODE node, uidnode;
KBNODE keyblock_orig = NULL;
KBPOS kbpos;
u32 keyid[2];
int rc = 0;
int new_key = 0;
int mod_key = 0;
/* get the key and print some info about it */
node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
if( !node )
BUG();
pk = node->pkt->pkt.public_key;
keyid_from_pk( pk, keyid );
uidnode = find_next_kbnode( keyblock, PKT_USER_ID );
if( opt.verbose ) {
log_info_f( fname, "pub %4u%c/%08lX %s ",
nbits_from_pk( pk ),
pubkey_letter( pk->pubkey_algo ),
(ulong)keyid[1], datestr_from_pk(pk) );
if( uidnode )
print_string( stderr, uidnode->pkt->pkt.user_id->name,
uidnode->pkt->pkt.user_id->len, 0 );
putc('\n', stderr);
}
if( !uidnode ) {
log_error_f(fname, _("key %08lX: no user id\n"), (ulong)keyid[1]);
return 0;
}
clear_kbnode_flags( keyblock );
rc = chk_self_sigs( fname, keyblock , pk, keyid );
if( rc )
return rc== -1? 0:rc;
if( !delete_inv_parts( fname, keyblock, keyid ) ) {
if( !opt.quiet ) {
log_info_f( fname, _("key %08lX: no valid user ids\n"),
(ulong)keyid[1]);
log_info(_("this may be caused by a missing self-signature\n"));
}
stats.no_user_id++;
return 0;
}
/* do we have this key already in one of our pubrings ? */
pk_orig = m_alloc_clear( sizeof *pk_orig );
rc = get_pubkey( pk_orig, keyid );
if( rc && rc != G10ERR_NO_PUBKEY ) {
log_error_f( fname, _("key %08lX: public key not found: %s\n"),
(ulong)keyid[1], g10_errstr(rc));
}
else if( rc ) { /* insert this key */
/* get default resource */
if( get_keyblock_handle( NULL, 0, &kbpos ) ) {
log_error(_("no default public keyring\n"));
return G10ERR_GENERAL;
}
if( opt.verbose > 1 )
log_info_f( fname, _("writing to '%s'\n"),
keyblock_resource_name(&kbpos) );
if( (rc=lock_keyblock( &kbpos )) )
log_error_f( keyblock_resource_name(&kbpos),
_("can't lock public keyring: %s\n"), g10_errstr(rc) );
else if( (rc=insert_keyblock( &kbpos, keyblock )) )
log_error_f( keyblock_resource_name(&kbpos),
_("can't write to keyring: %s\n"), g10_errstr(rc) );
unlock_keyblock( &kbpos );
/* we are ready */
if( !opt.quiet )
log_info_f( fname, _("key %08lX: public key imported\n"),
(ulong)keyid[1]);
stats.imported++;
if( is_RSA( pk->pubkey_algo ) )
stats.imported_rsa++;
new_key = 1;
}
else { /* merge */
int n_uids, n_sigs, n_subk;
/* Compare the original against the new key; just to be sure nothing
* weird is going on */
if( cmp_public_keys( pk_orig, pk ) ) {
log_error_f( fname, _("key %08lX: doesn't match our copy\n"),
(ulong)keyid[1]);
rc = G10ERR_GENERAL;
goto leave;
}
/* See whether we have only non-self-signature on one user id; if not
* ask the user what to do. <--- fixme */
/* now read the original keyblock */
rc = find_keyblock_bypk( &kbpos, pk_orig );
if( rc ) {
log_error_f(fname,
_("key %08lX: can't locate original keyblock: %s\n"),
(ulong)keyid[1], g10_errstr(rc));
goto leave;
}
rc = read_keyblock( &kbpos, &keyblock_orig );
if( rc ) {
log_error_f(fname,
_("key %08lX: can't read original keyblock: %s\n"),
(ulong)keyid[1], g10_errstr(rc));
goto leave;
}
/* and try to merge the block */
clear_kbnode_flags( keyblock_orig );
clear_kbnode_flags( keyblock );
n_uids = n_sigs = n_subk = 0;
rc = merge_blocks( fname, keyblock_orig, keyblock,
keyid, &n_uids, &n_sigs, &n_subk );
if( rc )
goto leave;
if( n_uids || n_sigs || n_subk ) {
mod_key = 1;
/* keyblock_orig has been updated; write */
if( opt.verbose > 1 )
log_info_f(keyblock_resource_name(&kbpos),
_("writing keyblock\n"));
if( (rc=lock_keyblock( &kbpos )) )
log_error_f(keyblock_resource_name(&kbpos),
_("can't lock public keyring: %s\n"), g10_errstr(rc) );
else if( (rc=update_keyblock( &kbpos, keyblock_orig )) )
log_error_f( keyblock_resource_name(&kbpos),
_("can't write keyblock: %s\n"), g10_errstr(rc) );
unlock_keyblock( &kbpos );
/* we are ready */
if( !opt.quiet ) {
if( n_uids == 1 )
log_info_f(fname, _("key %08lX: 1 new user-id\n"),
(ulong)keyid[1]);
else if( n_uids )
log_info_f(fname, _("key %08lX: %d new user-ids\n"),
(ulong)keyid[1], n_uids );
if( n_sigs == 1 )
log_info_f(fname, _("key %08lX: 1 new signature\n"),
(ulong)keyid[1]);
else if( n_sigs )
log_info_f(fname, _("key %08lX: %d new signatures\n"),
(ulong)keyid[1], n_sigs );
if( n_subk == 1 )
log_info_f(fname, _("key %08lX: 1 new subkey\n"),
(ulong)keyid[1]);
else if( n_subk )
log_info_f(fname, _("key %08lX: %d new subkeys\n"),
(ulong)keyid[1], n_subk );
}
stats.n_uids +=n_uids;
stats.n_sigs +=n_sigs;
stats.n_subk +=n_subk;
}
else {
if( !opt.quiet )
log_info_f(fname, _("key %08lX: not changed\n"),
(ulong)keyid[1] );
stats.unchanged++;
}
}
if( !rc && !fast ) {
rc = query_trust_record( new_key? pk : pk_orig );
if( rc && rc != -1 )
log_error("trustdb error: %s\n", g10_errstr(rc) );
else if( rc == -1 ) { /* not found trustdb */
rc = insert_trust_record( new_key? pk : pk_orig );
if( rc )
log_error("key %08lX: trustdb insert failed: %s\n",
(ulong)keyid[1], g10_errstr(rc) );
}
else if( mod_key )
rc = update_trust_record( keyblock_orig, 1, NULL );
else
rc = clear_trust_checked_flag( new_key? pk : pk_orig );
}
leave:
release_kbnode( keyblock_orig );
free_public_key( pk_orig );
return rc;
}
/****************
* Ditto for secret keys. Handling is simpler than for public keys.
*/
static int
import_secret_one( const char *fname, KBNODE keyblock )
{
PKT_secret_key *sk;
KBNODE node, uidnode;
KBPOS kbpos;
u32 keyid[2];
int rc = 0;
/* get the key and print some info about it */
node = find_kbnode( keyblock, PKT_SECRET_KEY );
if( !node )
BUG();
sk = node->pkt->pkt.secret_key;
keyid_from_sk( sk, keyid );
uidnode = find_next_kbnode( keyblock, PKT_USER_ID );
if( opt.verbose ) {
log_info_f(fname, "sec %4u%c/%08lX %s ",
nbits_from_sk( sk ),
pubkey_letter( sk->pubkey_algo ),
(ulong)keyid[1], datestr_from_sk(sk) );
if( uidnode )
print_string( stderr, uidnode->pkt->pkt.user_id->name,
uidnode->pkt->pkt.user_id->len, 0 );
putc('\n', stderr);
}
stats.secret_read++;
if( !uidnode ) {
log_error_f(fname, _("key %08lX: no user id\n"), (ulong)keyid[1]);
return 0;
}
clear_kbnode_flags( keyblock );
/* do we have this key already in one of our secrings ? */
rc = seckey_available( keyid );
if( rc == G10ERR_NO_SECKEY ) { /* simply insert this key */
/* get default resource */
if( get_keyblock_handle( NULL, 1, &kbpos ) ) {
log_error("no default secret keyring\n");
return G10ERR_GENERAL;
}
if( opt.verbose > 1 )
log_info_f(keyblock_resource_name(&kbpos), _("writing keyblock\n"));
if( (rc=lock_keyblock( &kbpos )) )
log_error_f( keyblock_resource_name(&kbpos),
_("can't lock secret keyring: %s\n"), g10_errstr(rc) );
else if( (rc=insert_keyblock( &kbpos, keyblock )) )
log_error_f(keyblock_resource_name(&kbpos),
_("can't write keyring: %s\n"), g10_errstr(rc) );
unlock_keyblock( &kbpos );
/* we are ready */
log_info_f(fname, _("key %08lX: secret key imported\n"), (ulong)keyid[1]);
stats.secret_imported++;
}
else if( !rc ) { /* we can't merge secret keys */
log_error_f(fname, _("key %08lX: already in secret keyring\n"),
(ulong)keyid[1]);
stats.secret_dups++;
}
else
log_error_f(fname, _("key %08lX: secret key not found: %s\n"),
(ulong)keyid[1], g10_errstr(rc));
return rc;
}
/****************
* Import a revocation certificate; this is a single signature packet.
*/
static int
import_revoke_cert( const char *fname, KBNODE node )
{
PKT_public_key *pk=NULL;
KBNODE onode, keyblock = NULL;
KBPOS kbpos;
u32 keyid[2];
int rc = 0;
assert( !node->next );
assert( node->pkt->pkttype == PKT_SIGNATURE );
assert( node->pkt->pkt.signature->sig_class == 0x20 );
keyid[0] = node->pkt->pkt.signature->keyid[0];
keyid[1] = node->pkt->pkt.signature->keyid[1];
pk = m_alloc_clear( sizeof *pk );
rc = get_pubkey( pk, keyid );
if( rc == G10ERR_NO_PUBKEY ) {
log_info_f(fname, _("key %08lX: no public key - "
"can't apply revocation certificate\n"), (ulong)keyid[1]);
rc = 0;
goto leave;
}
else if( rc ) {
log_error_f(fname, _("key %08lX: public key not found: %s\n"),
(ulong)keyid[1], g10_errstr(rc));
goto leave;
}
/* read the original keyblock */
rc = find_keyblock_bypk( &kbpos, pk );
if( rc ) {
log_error_f(fname,
_("key %08lX: can't locate original keyblock: %s\n"),
(ulong)keyid[1], g10_errstr(rc));
goto leave;
}
rc = read_keyblock( &kbpos, &keyblock );
if( rc ) {
log_error_f(fname,
_("key %08lX: can't read original keyblock: %s\n"),
(ulong)keyid[1], g10_errstr(rc));
goto leave;
}
/* it is okay, that node is not in keyblock because
* check_key_signature works fine for sig_class 0x20 in this
* special case. */
rc = check_key_signature( keyblock, node, NULL);
if( rc ) {
log_error_f(fname, _("key %08lX: invalid revocation certificate"
": %s - rejected\n"), (ulong)keyid[1], g10_errstr(rc));
}
/* check whether we already have this */
for(onode=keyblock->next; onode; onode=onode->next ) {
if( onode->pkt->pkttype == PKT_USER_ID )
break;
else if( onode->pkt->pkttype == PKT_SIGNATURE
&& onode->pkt->pkt.signature->sig_class == 0x20
&& keyid[0] == onode->pkt->pkt.signature->keyid[0]
&& keyid[1] == onode->pkt->pkt.signature->keyid[1] ) {
rc = 0;
goto leave; /* yes, we already know about it */
}
}
/* insert it */
insert_kbnode( keyblock, clone_kbnode(node), 0 );
/* and write the keyblock back */
if( opt.verbose > 1 )
log_info_f( keyblock_resource_name(&kbpos), _("writing keyblock\n"));
if( (rc=lock_keyblock( &kbpos )) )
log_error_f( keyblock_resource_name(&kbpos),
_("can't lock public keyring: %s\n"), g10_errstr(rc) );
else if( (rc=update_keyblock( &kbpos, keyblock )) )
log_error_f(keyblock_resource_name(&kbpos),
_("can't write keyblock: %s\n"), g10_errstr(rc) );
unlock_keyblock( &kbpos );
/* we are ready */
if( !opt.quiet )
log_info_f(fname, _("key %08lX: revocation certificate imported\n"),
(ulong)keyid[1]);
stats.n_revoc++;
leave:
release_kbnode( keyblock );
free_public_key( pk );
return rc;
}
/****************
* loop over the keyblock and check all self signatures.
* Mark all user-ids with a self-signature by setting flag bit 0.
* Mark all user-ids with an invalid self-signature by setting bit 1.
*/
static int
chk_self_sigs( const char *fname, KBNODE keyblock,
PKT_public_key *pk, u32 *keyid )
{
KBNODE n, unode;
PKT_signature *sig;
int rc;
for( n=keyblock; (n = find_next_kbnode(n, 0)); ) {
if( n->pkt->pkttype != PKT_SIGNATURE )
continue;
sig = n->pkt->pkt.signature;
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) {
unode = find_prev_kbnode( keyblock, n, PKT_USER_ID );
if( !unode ) {
log_error_f(fname, _("key %08lX: no user-id for signature\n"),
(ulong)keyid[1]);
return -1; /* the complete keyblock is invalid */
}
rc = check_key_signature( keyblock, n, NULL);
if( rc ) {
log_error_f( fname, rc == G10ERR_PUBKEY_ALGO ?
_("key %08lX: unsupported public key algorithm\n"):
_("key %08lX: invalid self-signature\n"),
(ulong)keyid[1]);
unode->flag |= 2; /* mark as invalid */
}
unode->flag |= 1; /* mark that signature checked */
}
}
return 0;
}
/****************
* delete all parts which are invalid and those signatures whose
* public key algorithm is not available in this implemenation;
* but consider RSA as valid, because parse/build_packets knows
* about it.
* returns: true if at least one valid user-id is left over.
*/
static int
delete_inv_parts( const char *fname, KBNODE keyblock, u32 *keyid )
{
KBNODE node;
int nvalid=0, uid_seen=0;
for(node=keyblock->next; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID ) {
uid_seen = 1;
if( (node->flag & 2) || !(node->flag & 1) ) {
if( opt.verbose ) {
log_info_f(fname, _("key %08lX: skipped userid '"),
(ulong)keyid[1]);
print_string( stderr, node->pkt->pkt.user_id->name,
node->pkt->pkt.user_id->len, 0 );
fputs("'\n", stderr );
}
delete_kbnode( node ); /* the user-id */
/* and all following packets up to the next user-id */
while( node->next && node->next->pkt->pkttype != PKT_USER_ID ){
delete_kbnode( node->next );
node = node->next;
}
}
else
nvalid++;
}
else if( node->pkt->pkttype == PKT_SIGNATURE
&& check_pubkey_algo( node->pkt->pkt.signature->pubkey_algo)
&& node->pkt->pkt.signature->pubkey_algo != PUBKEY_ALGO_RSA )
delete_kbnode( node ); /* build_packet() can't handle this */
else if( node->pkt->pkttype == PKT_SIGNATURE
&& node->pkt->pkt.signature->sig_class == 0x20 ) {
if( uid_seen ) {
log_error_f(fname, _("key %08lX: revocation certificate "
"at wrong place - skipped\n"),
(ulong)keyid[1]);
delete_kbnode( node );
}
else {
int rc = check_key_signature( keyblock, node, NULL);
if( rc ) {
log_error_f(fname, _("key %08lX: invalid revocation "
"certificate: %s - skipped\n"),
(ulong)keyid[1], g10_errstr(rc));
delete_kbnode( node );
}
}
}
}
/* note: because keyblock is the public key, it is never marked
* for deletion and so keyblock cannot change */
commit_kbnode( &keyblock );
return nvalid;
}
/****************
* compare and merge the blocks
*
* o compare the signatures: If we already have this signature, check
* that they compare okay; if not, issue a warning and ask the user.
* o Simply add the signature. Can't verify here because we may not have
* the signature's public key yet; verification is done when putting it
* into the trustdb, which is done automagically as soon as this pubkey
* is used.
* Note: We indicate newly inserted packets with flag bit 0
*/
static int
merge_blocks( const char *fname, KBNODE keyblock_orig, KBNODE keyblock,
u32 *keyid, int *n_uids, int *n_sigs, int *n_subk )
{
KBNODE onode, node;
int rc, found;
/* 1st: handle revocation certificates */
for(node=keyblock->next; node; node=node->next ) {
if( node->pkt->pkttype == PKT_USER_ID )
break;
else if( node->pkt->pkttype == PKT_SIGNATURE
&& node->pkt->pkt.signature->sig_class == 0x20 ) {
/* check whether we already have this */
found = 0;
for(onode=keyblock_orig->next; onode; onode=onode->next ) {
if( onode->pkt->pkttype == PKT_USER_ID )
break;
else if( onode->pkt->pkttype == PKT_SIGNATURE
&& onode->pkt->pkt.signature->sig_class == 0x20
&& node->pkt->pkt.signature->keyid[0]
== onode->pkt->pkt.signature->keyid[0]
&& node->pkt->pkt.signature->keyid[1]
== onode->pkt->pkt.signature->keyid[1] ) {
found = 1;
break;
}
}
if( !found ) {
KBNODE n2 = clone_kbnode(node);
insert_kbnode( keyblock_orig, n2, 0 );
n2->flag |= 1;
log_info_f(fname, _("key %08lX: revocation certificate added\n"),
(ulong)keyid[1]);
}
}
}
/* 2nd: try to merge new certificates in */
for(onode=keyblock_orig->next; onode; onode=onode->next ) {
if( !(onode->flag & 1) && onode->pkt->pkttype == PKT_USER_ID) {
/* find the user id in the imported keyblock */
for(node=keyblock->next; node; node=node->next )
if( node->pkt->pkttype == PKT_USER_ID
&& !cmp_user_ids( onode->pkt->pkt.user_id,
node->pkt->pkt.user_id ) )
break;
if( node ) { /* found: merge */
rc = merge_sigs( onode, node, n_sigs, fname, keyid );
if( rc )
return rc;
}
}
}
/* 3rd: add new user-ids */
for(node=keyblock->next; node; node=node->next ) {
if( node->pkt->pkttype == PKT_USER_ID) {
/* do we have this in the original keyblock */
for(onode=keyblock_orig->next; onode; onode=onode->next )
if( onode->pkt->pkttype == PKT_USER_ID
&& !cmp_user_ids( onode->pkt->pkt.user_id,
node->pkt->pkt.user_id ) )
break;
if( !onode ) { /* this is a new user id: append */
rc = append_uid( keyblock_orig, node, n_sigs, fname, keyid);
if( rc )
return rc;
++*n_uids;
}
}
}
/* merge subkey certifcates */
for(onode=keyblock_orig->next; onode; onode=onode->next ) {
if( !(onode->flag & 1)
&& ( onode->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| onode->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
/* find the subkey in the imported keyblock */
for(node=keyblock->next; node; node=node->next ) {
if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
&& !cmp_public_keys( onode->pkt->pkt.public_key,
node->pkt->pkt.public_key ) )
break;
else if( node->pkt->pkttype == PKT_SECRET_SUBKEY
&& !cmp_secret_keys( onode->pkt->pkt.secret_key,
node->pkt->pkt.secret_key ) )
break;
}
if( node ) { /* found: merge */
rc = merge_keysigs( onode, node, n_sigs, fname, keyid );
if( rc )
return rc;
}
}
}
/* add new subkeys */
for(node=keyblock->next; node; node=node->next ) {
onode = NULL;
if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
/* do we have this in the original keyblock? */
for(onode=keyblock_orig->next; onode; onode=onode->next )
if( onode->pkt->pkttype == PKT_PUBLIC_SUBKEY
&& !cmp_public_keys( onode->pkt->pkt.public_key,
node->pkt->pkt.public_key ) )
break;
if( !onode ) { /* this is a new subkey: append */
rc = append_key( keyblock_orig, node, n_sigs, fname, keyid);
if( rc )
return rc;
++*n_subk;
}
}
else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
/* do we have this in the original keyblock? */
for(onode=keyblock_orig->next; onode; onode=onode->next )
if( onode->pkt->pkttype == PKT_SECRET_SUBKEY
&& !cmp_secret_keys( onode->pkt->pkt.secret_key,
node->pkt->pkt.secret_key ) )
break;
if( !onode ) { /* this is a new subkey: append */
rc = append_key( keyblock_orig, node, n_sigs, fname, keyid);
if( rc )
return rc;
++*n_subk;
}
}
}
return 0;
}
/****************
* append the userid starting with NODE and all signatures to KEYBLOCK.
* Mark all new and copied packets by setting flag bit 0.
*/
static int
append_uid( KBNODE keyblock, KBNODE node, int *n_sigs,
const char *fname, u32 *keyid )
{
KBNODE n, n_where=NULL;
assert(node->pkt->pkttype == PKT_USER_ID );
if( node->next->pkt->pkttype == PKT_USER_ID ) {
log_error_f(fname, _("key %08lX: our copy has no self-signature\n"),
(ulong)keyid[1]);
return G10ERR_GENERAL;
}
/* find the position */
for( n = keyblock; n; n_where = n, n = n->next ) {
if( n->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| n->pkt->pkttype == PKT_SECRET_SUBKEY )
break;
}
if( !n )
n_where = NULL;
/* and append/insert */
while( node ) {
/* we add a clone to the original keyblock, because this
* one is released first */
n = clone_kbnode(node);
if( n_where ) {
insert_kbnode( n_where, n, 0 );
n_where = n;
}
else
add_kbnode( keyblock, n );
n->flag |= 1;
node->flag |= 1;
if( n->pkt->pkttype == PKT_SIGNATURE )
++*n_sigs;
node = node->next;
if( node && node->pkt->pkttype != PKT_SIGNATURE )
break;
}
return 0;
}
/****************
* Merge the sigs from SRC onto DST. SRC and DST are both a PKT_USER_ID.
* (how should we handle comment packets here?)
*/
static int
merge_sigs( KBNODE dst, KBNODE src, int *n_sigs,
const char *fname, u32 *keyid )
{
KBNODE n, n2;
int found=0;
assert(dst->pkt->pkttype == PKT_USER_ID );
assert(src->pkt->pkttype == PKT_USER_ID );
/* at least a self signature comes next to the user-ids */
assert(src->next->pkt->pkttype != PKT_USER_ID );
if( dst->next->pkt->pkttype == PKT_USER_ID ) {
log_error_f(fname, _("key %08lX: our copy has no self-signature\n"),
(ulong)keyid[1]);
return 0;
}
for(n=src->next; n && n->pkt->pkttype != PKT_USER_ID; n = n->next ) {
if( n->pkt->pkttype != PKT_SIGNATURE )
continue;
found = 0;
for(n2=dst->next; n2 && n2->pkt->pkttype != PKT_USER_ID; n2 = n2->next){
if( n2->pkt->pkttype == PKT_SIGNATURE
&& n->pkt->pkt.signature->keyid[0]
== n2->pkt->pkt.signature->keyid[0]
&& n->pkt->pkt.signature->keyid[1]
== n2->pkt->pkt.signature->keyid[1]
&& n->pkt->pkt.signature->timestamp
<= n2->pkt->pkt.signature->timestamp
&& n->pkt->pkt.signature->sig_class
== n2->pkt->pkt.signature->sig_class ) {
found++;
break;
}
}
if( !found ) {
/* This signature is new or newer, append N to DST.
* We add a clone to the original keyblock, because this
* one is released first */
n2 = clone_kbnode(n);
insert_kbnode( dst, n2, PKT_SIGNATURE );
n2->flag |= 1;
n->flag |= 1;
++*n_sigs;
}
}
return 0;
}
/****************
* Merge the sigs from SRC onto DST. SRC and DST are both a PKT_xxx_SUBKEY.
*/
static int
merge_keysigs( KBNODE dst, KBNODE src, int *n_sigs,
const char *fname, u32 *keyid )
{
KBNODE n, n2;
int found=0;
assert( dst->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| dst->pkt->pkttype == PKT_SECRET_SUBKEY );
for(n=src->next; n ; n = n->next ) {
if( n->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| n->pkt->pkttype == PKT_PUBLIC_KEY )
break;
if( n->pkt->pkttype != PKT_SIGNATURE )
continue;
found = 0;
for(n2=dst->next; n2; n2 = n2->next){
if( n2->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| n2->pkt->pkttype == PKT_PUBLIC_KEY )
break;
if( n2->pkt->pkttype == PKT_SIGNATURE
&& n->pkt->pkt.signature->keyid[0]
== n2->pkt->pkt.signature->keyid[0]
&& n->pkt->pkt.signature->keyid[1]
== n2->pkt->pkt.signature->keyid[1]
&& n->pkt->pkt.signature->timestamp
<= n2->pkt->pkt.signature->timestamp
&& n->pkt->pkt.signature->sig_class
== n2->pkt->pkt.signature->sig_class ) {
found++;
break;
}
}
if( !found ) {
/* This signature is new or newer, append N to DST.
* We add a clone to the original keyblock, because this
* one is released first */
n2 = clone_kbnode(n);
insert_kbnode( dst, n2, PKT_SIGNATURE );
n2->flag |= 1;
n->flag |= 1;
++*n_sigs;
}
}
return 0;
}
/****************
* append the subkey starting with NODE and all signatures to KEYBLOCK.
* Mark all new and copied packets by setting flag bit 0.
*/
static int
append_key( KBNODE keyblock, KBNODE node, int *n_sigs,
const char *fname, u32 *keyid )
{
KBNODE n;
assert( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype == PKT_SECRET_SUBKEY );
while( node ) {
/* we add a clone to the original keyblock, because this
* one is released first */
n = clone_kbnode(node);
add_kbnode( keyblock, n );
n->flag |= 1;
node->flag |= 1;
if( n->pkt->pkttype == PKT_SIGNATURE )
++*n_sigs;
node = node->next;
if( node && node->pkt->pkttype != PKT_SIGNATURE )
break;
}
return 0;
}
diff --git a/g10/kbnode.c b/g10/kbnode.c
index 1048f316d..70c85f7bd 100644
--- a/g10/kbnode.c
+++ b/g10/kbnode.c
@@ -1,317 +1,317 @@
/* kbnode.c - keyblock node utility functions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "packet.h"
#include "keydb.h"
#define USE_UNUSED_NODES 1
static KBNODE unused_nodes;
KBNODE
new_kbnode( PACKET *pkt )
{
KBNODE n;
n = unused_nodes;
if( n )
unused_nodes = n->next;
else
n = m_alloc( sizeof *n );
n->next = NULL;
n->pkt = pkt;
n->flag = 0;
n->private_flag=0;
n->recno = 0;
return n;
}
KBNODE
clone_kbnode( KBNODE node )
{
KBNODE n;
n = unused_nodes;
if( n )
unused_nodes = n->next;
else
n = m_alloc( sizeof *n );
n->next = NULL;
n->pkt = node->pkt;
n->flag = 0;
n->private_flag = node->private_flag | 2; /* mark cloned */
return n;
}
void
release_kbnode( KBNODE n )
{
KBNODE n2;
while( n ) {
n2 = n->next;
if( !(n->private_flag & 2) ) {
free_packet( n->pkt );
m_free( n->pkt );
}
#if USE_UNUSED_NODES
n->next = unused_nodes;
unused_nodes = n;
#else
m_free( n );
#endif
n = n2;
}
}
/****************
* Delete NODE from ROOT. ROOT must exist!
* Note: This only works with walk_kbnode!!
*/
void
delete_kbnode( KBNODE node )
{
node->private_flag |= 1;
}
/****************
* Append NODE to ROOT. ROOT must exist!
*/
void
add_kbnode( KBNODE root, KBNODE node )
{
KBNODE n1;
for(n1=root; n1->next; n1 = n1->next)
;
n1->next = node;
}
/****************
* Insert NODE into the list after root but before a packet which is not of
* type PKTTYPE
* (only if PKTTYPE != 0)
*/
void
insert_kbnode( KBNODE root, KBNODE node, int pkttype )
{
if( !pkttype ) {
node->next = root->next;
root->next = node;
}
else {
KBNODE n1;
for(n1=root; n1->next; n1 = n1->next)
if( pkttype != n1->next->pkt->pkttype ) {
node->next = n1->next;
n1->next = node;
return;
}
/* no such packet, append */
node->next = NULL;
n1->next = node;
}
}
/****************
* Find the previous node (if PKTTYPE = 0) or the previous node
* with pkttype PKTTYPE in the list starting with ROOT of NODE.
*/
KBNODE
find_prev_kbnode( KBNODE root, KBNODE node, int pkttype )
{
KBNODE n1;
for(n1=NULL ; root && root != node; root = root->next )
if( !pkttype || root->pkt->pkttype == pkttype )
n1 = root;
return n1;
}
/****************
* Ditto, but find the next packet. The behaviour is trivial if
* PKTTYPE is 0 but if it is specified, the next node with a packet
* of this type is returned. The function has some knowledge about
* the valid ordering of packets: e.g. if the next signature packet
* is requested, the function will not return one if it encounters
* a user-id.
*/
KBNODE
find_next_kbnode( KBNODE node, int pkttype )
{
for( node=node->next ; node; node = node->next ) {
if( !pkttype )
return node;
else if( pkttype == PKT_USER_ID
&& ( node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_SECRET_KEY ) )
return NULL;
else if( pkttype == PKT_SIGNATURE
&& ( node->pkt->pkttype == PKT_USER_ID
|| node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_SECRET_KEY ) )
return NULL;
else if( node->pkt->pkttype == pkttype )
return node;
}
return NULL;
}
KBNODE
find_kbnode( KBNODE node, int pkttype )
{
for( ; node; node = node->next ) {
if( node->pkt->pkttype == pkttype )
return node;
}
return NULL;
}
/****************
* Walk through a list of kbnodes. This function returns
* the next kbnode for each call; before using the function the first
* time, the caller must set CONTEXT to NULL (This has simply the effect
* to start with ROOT).
*/
KBNODE
walk_kbnode( KBNODE root, KBNODE *context, int all )
{
KBNODE n;
do {
if( !*context ) {
*context = root;
n = root;
}
else {
n = (*context)->next;
*context = n;
}
} while( !all && n && (n->private_flag & 1) );
return n;
}
void
clear_kbnode_flags( KBNODE n )
{
for( ; n; n = n->next ) {
n->flag = 0;
}
}
/****************
* Commit changes made to the kblist at ROOT. Note that ROOT my change,
* and it is therefore passed by reference.
* The function has the effect of removing all nodes marked as deleted.
* returns true if any node has been changed
*/
int
commit_kbnode( KBNODE *root )
{
KBNODE n, nl;
int changed = 0;
for( n = *root, nl=NULL; n; n = nl->next ) {
if( (n->private_flag & 1) ) {
if( n == *root )
*root = nl = n->next;
else
nl->next = n->next;
if( !(n->private_flag & 2) ) {
free_packet( n->pkt );
m_free( n->pkt );
}
#if USE_UNUSED_NODES
n->next = unused_nodes;
unused_nodes = n;
#else
m_free( n );
#endif
changed = 1;
}
else
nl = n;
}
return changed;
}
void
dump_kbnode( KBNODE node )
{
for(; node; node = node->next ) {
const char *s;
switch( node->pkt->pkttype ) {
case 0: s="empty"; break;
case PKT_PUBLIC_KEY: s="public-key"; break;
case PKT_SECRET_KEY: s="secret-key"; break;
case PKT_SECRET_SUBKEY: s= "secret-subkey"; break;
case PKT_PUBKEY_ENC: s="public-enc"; break;
case PKT_SIGNATURE: s="signature"; break;
case PKT_ONEPASS_SIG: s="onepass-sig"; break;
case PKT_USER_ID: s="user-id"; break;
case PKT_PUBLIC_SUBKEY: s="public-subkey"; break;
case PKT_COMMENT: s="comment"; break;
case PKT_RING_TRUST: s="trust"; break;
case PKT_PLAINTEXT: s="plaintext"; break;
case PKT_COMPRESSED: s="compressed"; break;
case PKT_ENCRYPTED: s="encrypted"; break;
default: s="unknown"; break;
}
fprintf(stderr, "node %p %02x/%02x type=%s",
node, node->flag, node->private_flag, s);
if( node->pkt->pkttype == PKT_USER_ID ) {
fputs(" \"", stderr);
print_string( stderr, node->pkt->pkt.user_id->name,
node->pkt->pkt.user_id->len, 0 );
fputs("\"\n", stderr);
}
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
fprintf(stderr, " keyid=%08lX\n",
(ulong)node->pkt->pkt.signature->keyid[1] );
}
else if( node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
fprintf(stderr, " keyid=%08lX\n", (ulong)
keyid_from_pk( node->pkt->pkt.public_key, NULL ));
}
else
fputs("\n", stderr);
}
}
diff --git a/g10/keydb.h b/g10/keydb.h
index a3abbe76f..1d1c6c26c 100644
--- a/g10/keydb.h
+++ b/g10/keydb.h
@@ -1,204 +1,206 @@
/* keydb.h - Key database
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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_KEYDB_H
#define G10_KEYDB_H
#ifdef HAVE_LIBGDBM
#include <gdbm.h>
#endif
#include "types.h"
#include "packet.h"
#include "cipher.h"
#define MAX_FINGERPRINT_LEN 20
typedef struct getkey_ctx_s *GETKEY_CTX;
#ifndef DEFINES_GETKEY_CTX
struct getkey_ctx_s { char hidden[1]; };
#endif
/****************
* A Keyblock is all packets which form an entire certificate;
* i.e. the public key, certificate, trust packets, user ids,
* signatures, and subkey.
*
* This structure is also used to bind arbitrary packets together.
*/
typedef struct kbnode_struct *KBNODE;
struct kbnode_struct {
KBNODE next;
PACKET *pkt;
int flag;
int private_flag;
ulong recno; /* used while updating the trustdb */
};
enum resource_type {
rt_UNKNOWN = 0,
rt_RING = 1,
rt_GDBM = 2
};
/****************
* A data structre to hold information about the external position
* of a keyblock.
*/
struct keyblock_pos_struct {
int resno; /* resource number */
enum resource_type rt;
ulong offset; /* position information */
unsigned count; /* length of the keyblock in packets */
IOBUF fp; /* used by enum_keyblocks */
int secret; /* working on a secret keyring */
#ifdef HAVE_LIBGDBM
GDBM_FILE dbf;
byte keybuf[21];
#endif
PACKET *pkt; /* ditto */
+ int valid;
};
typedef struct keyblock_pos_struct KBPOS;
/* structure to hold a couple of public key certificates */
typedef struct pk_list *PK_LIST;
struct pk_list {
PK_LIST next;
PKT_public_key *pk;
int mark;
};
/* structure to hold a couple of secret key certificates */
typedef struct sk_list *SK_LIST;
struct sk_list {
SK_LIST next;
PKT_secret_key *sk;
int mark;
};
/* structure to collect all information which can be used to
* identify a public key */
typedef struct pubkey_find_info *PUBKEY_FIND_INFO;
struct pubkey_find_info {
u32 keyid[2];
unsigned nbits;
byte pubkey_algo;
byte fingerprint[MAX_FINGERPRINT_LEN];
char userid[1];
};
/*-- pkclist.c --*/
int check_signatures_trust( PKT_signature *sig );
void release_pk_list( PK_LIST pk_list );
int build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned usage );
int select_algo_from_prefs( PK_LIST pk_list, int preftype );
/*-- skclist.c --*/
void release_sk_list( SK_LIST sk_list );
int build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list,
int unlock, unsigned usage );
/*-- passphrase.h --*/
int have_static_passphrase(void);
void read_passphrase_from_fd( int fd );
DEK *passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode);
void set_next_passphrase( const char *s );
char *get_last_passphrase(void);
/*-- getkey.c --*/
int classify_user_id( const char *name, u32 *keyid, byte *fprint,
const char **retstr, size_t *retlen );
+void getkey_disable_caches(void);
int get_pubkey( PKT_public_key *pk, u32 *keyid );
int get_pubkey_byname( GETKEY_CTX *rx, PKT_public_key *pk,
const char *name, KBNODE *ret_keyblock );
int get_pubkey_next( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock );
void get_pubkey_end( GETKEY_CTX ctx );
int get_seckey( PKT_secret_key *sk, u32 *keyid );
int get_pubkey_byfprint( PKT_public_key *pk, const byte *fprint,
size_t fprint_len );
int get_keyblock_byfprint( KBNODE *ret_keyblock, const byte *fprint,
size_t fprint_len );
int seckey_available( u32 *keyid );
int get_seckey_byname( PKT_secret_key *sk, const char *name, int unlock );
int enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys );
void merge_keys_and_selfsig( KBNODE keyblock );
char*get_user_id_string( u32 *keyid );
char*get_long_user_id_string( u32 *keyid );
char*get_user_id( u32 *keyid, size_t *rn );
/*-- keyid.c --*/
int pubkey_letter( int algo );
u32 keyid_from_sk( PKT_secret_key *sk, u32 *keyid );
u32 keyid_from_pk( PKT_public_key *pk, u32 *keyid );
u32 keyid_from_sig( PKT_signature *sig, u32 *keyid );
u32 keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid );
unsigned nbits_from_pk( PKT_public_key *pk );
unsigned nbits_from_sk( PKT_secret_key *sk );
const char *datestr_from_pk( PKT_public_key *pk );
const char *datestr_from_sk( PKT_secret_key *sk );
const char *datestr_from_sig( PKT_signature *sig );
const char *expirestr_from_pk( PKT_public_key *pk );
const char *expirestr_from_sk( PKT_secret_key *sk );
byte *fingerprint_from_sk( PKT_secret_key *sk, byte *buf, size_t *ret_len );
byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
/*-- kbnode.c --*/
KBNODE new_kbnode( PACKET *pkt );
KBNODE clone_kbnode( KBNODE node );
void release_kbnode( KBNODE n );
void delete_kbnode( KBNODE node );
void add_kbnode( KBNODE root, KBNODE node );
void insert_kbnode( KBNODE root, KBNODE node, int pkttype );
KBNODE find_prev_kbnode( KBNODE root, KBNODE node, int pkttype );
KBNODE find_next_kbnode( KBNODE node, int pkttype );
KBNODE find_kbnode( KBNODE node, int pkttype );
KBNODE walk_kbnode( KBNODE root, KBNODE *context, int all );
void clear_kbnode_flags( KBNODE n );
int commit_kbnode( KBNODE *root );
void dump_kbnode( KBNODE node );
/*-- ringedit.c --*/
const char *enum_keyblock_resources( int *sequence, int secret );
int add_keyblock_resource( const char *resname, int force, int secret );
const char *keyblock_resource_name( KBPOS *kbpos );
int get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos );
int locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr,
int fprlen, int secret );
int locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid,
int shortkid, int secret );
int find_keyblock( PUBKEY_FIND_INFO info, KBPOS *kbpos );
int find_keyblock_byname( KBPOS *kbpos, const char *username );
int find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk );
int find_secret_keyblock_byname( KBPOS *kbpos, const char *username );
int lock_keyblock( KBPOS *kbpos );
void unlock_keyblock( KBPOS *kbpos );
int read_keyblock( KBPOS *kbpos, KBNODE *ret_root );
int enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root );
int insert_keyblock( KBPOS *kbpos, KBNODE root );
int delete_keyblock( KBPOS *kbpos );
int update_keyblock( KBPOS *kbpos, KBNODE root );
#endif /*G10_KEYDB_H*/
diff --git a/g10/keyedit.c b/g10/keyedit.c
index b402b4f99..0a711c282 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -1,1452 +1,1452 @@
/* keyedit.c - keyedit stuff
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <ctype.h>
#include "options.h"
#include "packet.h"
#include "errors.h"
#include "iobuf.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "main.h"
#include "trustdb.h"
#include "filter.h"
#include "ttyio.h"
#include "status.h"
#include "i18n.h"
static void show_prefs( KBNODE keyblock, PKT_user_id *uid );
static void show_key_with_all_names( KBNODE keyblock,
int only_marked, int with_fpr, int with_subkeys, int with_prefs );
static void show_key_and_fingerprint( KBNODE keyblock );
static void show_fingerprint( PKT_public_key *pk );
static int menu_adduid( KBNODE keyblock, KBNODE sec_keyblock );
static void menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock );
static void menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock );
static int menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock );
static int menu_select_uid( KBNODE keyblock, int index );
static int menu_select_key( KBNODE keyblock, int index );
static int count_uids( KBNODE keyblock );
static int count_uids_with_flag( KBNODE keyblock, unsigned flag );
static int count_keys_with_flag( KBNODE keyblock, unsigned flag );
static int count_selected_uids( KBNODE keyblock );
static int count_selected_keys( KBNODE keyblock );
#define CONTROL_D ('D' - 'A' + 1)
#define NODFLG_BADSIG (1<<0) /* bad signature */
#define NODFLG_NOKEY (1<<1) /* no public key */
#define NODFLG_SIGERR (1<<2) /* other sig error */
#define NODFLG_MARK_A (1<<4) /* temporary mark */
#define NODFLG_SELUID (1<<8) /* indicate the selected userid */
#define NODFLG_SELKEY (1<<9) /* indicate the selected key */
static int
get_keyblock_byname( KBNODE *keyblock, KBPOS *kbpos, const char *username )
{
int rc;
*keyblock = NULL;
/* search the userid */
rc = find_keyblock_byname( kbpos, username );
if( rc ) {
log_error(_("%s: user not found\n"), username );
return rc;
}
/* read the keyblock */
rc = read_keyblock( kbpos, keyblock );
if( rc )
log_error("%s: keyblock read problem: %s\n", username, g10_errstr(rc));
else
merge_keys_and_selfsig( *keyblock );
return rc;
}
/****************
* Check the keysigs and set the flags to indicate errors.
* Returns true if error found.
*/
static int
check_all_keysigs( KBNODE keyblock, int only_selected )
{
KBNODE kbctx;
KBNODE node;
int rc;
int inv_sigs = 0;
int no_key = 0;
int oth_err = 0;
int has_selfsig = 0;
int mis_selfsig = 0;
int selected = !only_selected;
int anyuid = 0;
for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
if( node->pkt->pkttype == PKT_USER_ID ) {
PKT_user_id *uid = node->pkt->pkt.user_id;
if( only_selected )
selected = (node->flag & NODFLG_SELUID);
if( selected ) {
tty_printf("uid ");
tty_print_string( uid->name, uid->len );
tty_printf("\n");
if( anyuid && !has_selfsig )
mis_selfsig++;
has_selfsig = 0;
anyuid = 1;
}
}
else if( selected && node->pkt->pkttype == PKT_SIGNATURE
&& (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
PKT_signature *sig = node->pkt->pkt.signature;
int sigrc, selfsig;
switch( (rc = check_key_signature( keyblock, node, &selfsig)) ) {
case 0:
node->flag &= ~(NODFLG_BADSIG|NODFLG_NOKEY|NODFLG_SIGERR);
sigrc = '!';
break;
case G10ERR_BAD_SIGN:
node->flag = NODFLG_BADSIG;
sigrc = '-';
inv_sigs++;
break;
case G10ERR_NO_PUBKEY:
node->flag = NODFLG_NOKEY;
sigrc = '?';
no_key++;
break;
default:
node->flag = NODFLG_SIGERR;
sigrc = '%';
oth_err++;
break;
}
if( sigrc != '?' ) {
tty_printf("sig%c %08lX %s ",
sigrc, sig->keyid[1], datestr_from_sig(sig));
if( sigrc == '%' )
tty_printf("[%s] ", g10_errstr(rc) );
else if( sigrc == '?' )
;
else if( selfsig ) {
tty_printf( _("[self-signature]") );
if( sigrc == '!' )
has_selfsig = 1;
}
else {
size_t n;
char *p = get_user_id( sig->keyid, &n );
tty_print_string( p, n > 40? 40 : n );
m_free(p);
}
tty_printf("\n");
/* fixme: Should we update the trustdb here */
}
}
}
if( !has_selfsig )
mis_selfsig++;
if( inv_sigs == 1 )
tty_printf(_("1 bad signature\n"), inv_sigs );
else if( inv_sigs )
tty_printf(_("%d bad signatures\n"), inv_sigs );
if( no_key == 1 )
tty_printf(_("1 signature not checked due to a missing key\n") );
else if( no_key )
tty_printf(_("%d signatures not checked due to missing keys\n"), no_key );
if( oth_err == 1 )
tty_printf(_("1 signature not checked due to an error\n") );
else if( oth_err )
tty_printf(_("%d signatures not checked due to errors\n"), oth_err );
if( mis_selfsig == 1 )
tty_printf(_("1 user id without valid self-signature detected\n"));
else if( mis_selfsig )
tty_printf(_("%d user ids without valid self-signatures detected\n"),
mis_selfsig);
return inv_sigs || no_key || oth_err || mis_selfsig;
}
/****************
* Loop over all locusr and and sign the uids after asking.
* If no user id is marked, all user ids will be signed;
* if some user_ids are marked those will be signed.
*
* fixme: Add support for our proposed sign-all scheme
*/
static int
sign_uids( KBNODE keyblock, STRLIST locusr, int *ret_modified )
{
int rc = 0;
SK_LIST sk_list = NULL;
SK_LIST sk_rover = NULL;
PKT_secret_key *sk = NULL;
KBNODE node, uidnode;
PKT_public_key *primary_pk=NULL;
int select_all = !count_selected_uids(keyblock);
int upd_trust = 0;
/* build a list of all signators */
rc=build_sk_list( locusr, &sk_list, 0, 1 );
if( rc )
goto leave;
/* loop over all signaturs */
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
u32 sk_keyid[2];
size_t n;
char *p;
/* we have to use a copy of the sk, because make_keysig_packet
* may remove the protection from sk and if we did other
* changes to the secret key, we would save the unprotected
* version */
if( sk )
free_secret_key(sk);
sk = copy_secret_key( NULL, sk_rover->sk );
keyid_from_sk( sk, sk_keyid );
/* set mark A for all selected user ids */
for( node=keyblock; node; node = node->next ) {
if( select_all || (node->flag & NODFLG_SELUID) )
node->flag |= NODFLG_MARK_A;
else
node->flag &= ~NODFLG_MARK_A;
}
/* reset mark for uids which are already signed */
uidnode = NULL;
for( node=keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID ) {
uidnode = (node->flag & NODFLG_MARK_A)? node : NULL;
}
else if( uidnode && node->pkt->pkttype == PKT_SIGNATURE
&& (node->pkt->pkt.signature->sig_class&~3) == 0x10 ) {
if( sk_keyid[0] == node->pkt->pkt.signature->keyid[0]
&& sk_keyid[1] == node->pkt->pkt.signature->keyid[1] ) {
tty_printf(_("Already signed by key %08lX\n"),
(ulong)sk_keyid[1] );
uidnode->flag &= ~NODFLG_MARK_A; /* remove mark */
}
}
}
/* check whether any uids are left for signing */
if( !count_uids_with_flag(keyblock, NODFLG_MARK_A) ) {
tty_printf(_("Nothing to sign with key %08lX\n"),
(ulong)sk_keyid[1] );
continue;
}
/* Ask whether we really should sign these user id(s) */
tty_printf("\n");
show_key_with_all_names( keyblock, 1, 1, 0, 0 );
tty_printf("\n");
tty_printf(_(
"Are you really sure that you want to sign this key\n"
"with your key: \""));
p = get_user_id( sk_keyid, &n );
tty_print_string( p, n );
m_free(p); p = NULL;
tty_printf("\"\n\n");
if( !cpr_get_answer_is_yes("sign_uid.okay", _("Really sign? ")) )
continue;;
/* now we can sign the user ids */
reloop: /* (must use this, because we are modifing the list) */
primary_pk = NULL;
for( node=keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_PUBLIC_KEY )
primary_pk = node->pkt->pkt.public_key;
else if( node->pkt->pkttype == PKT_USER_ID
&& (node->flag & NODFLG_MARK_A) ) {
PACKET *pkt;
PKT_signature *sig;
assert( primary_pk );
node->flag &= ~NODFLG_MARK_A;
rc = make_keysig_packet( &sig, primary_pk,
node->pkt->pkt.user_id,
NULL,
sk,
0x10, 0, NULL, NULL );
if( rc ) {
log_error(_("signing failed: %s\n"), g10_errstr(rc));
goto leave;
}
*ret_modified = 1; /* we changed the keyblock */
upd_trust = 1;
pkt = m_alloc_clear( sizeof *pkt );
pkt->pkttype = PKT_SIGNATURE;
pkt->pkt.signature = sig;
insert_kbnode( node, new_kbnode(pkt), PKT_SIGNATURE );
goto reloop;
}
}
} /* end loop over signators */
if( upd_trust && primary_pk ) {
rc = clear_trust_checked_flag( primary_pk );
}
leave:
release_sk_list( sk_list );
if( sk )
free_secret_key(sk);
return rc;
}
/****************
* Change the passphrase of the primary and all secondary keys.
* We use only one passphrase for all keys.
*/
static int
change_passphrase( KBNODE keyblock )
{
int rc = 0;
int changed=0;
KBNODE node;
PKT_secret_key *sk;
char *passphrase = NULL;
node = find_kbnode( keyblock, PKT_SECRET_KEY );
if( !node ) {
log_error("Oops; secret key not found anymore!\n");
goto leave;
}
sk = node->pkt->pkt.secret_key;
switch( is_secret_key_protected( sk ) ) {
case -1:
rc = G10ERR_PUBKEY_ALGO;
break;
case 0:
tty_printf(_("This key is not protected.\n"));
break;
default:
tty_printf(_("Key is protected.\n"));
rc = check_secret_key( sk, 0 );
if( !rc )
passphrase = get_last_passphrase();
break;
}
/* unprotect all subkeys (use the supplied passphrase or ask)*/
for(node=keyblock; !rc && node; node = node->next ) {
if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
PKT_secret_key *subsk = node->pkt->pkt.secret_key;
set_next_passphrase( passphrase );
rc = check_secret_key( subsk, 0 );
}
}
if( rc )
tty_printf(_("Can't edit this key: %s\n"), g10_errstr(rc));
else {
DEK *dek = NULL;
STRING2KEY *s2k = m_alloc_secure( sizeof *s2k );
tty_printf(_("Enter the new passphrase for this secret key.\n\n") );
set_next_passphrase( NULL );
for(;;) {
s2k->mode = opt.s2k_mode;
s2k->hash_algo = opt.s2k_digest_algo;
dek = passphrase_to_dek( NULL, opt.s2k_cipher_algo, s2k, 2 );
if( !dek ) {
tty_printf(_("passphrase not correctly repeated; try again.\n"));
}
else if( !dek->keylen ) {
rc = 0;
tty_printf(_( "You don't want a passphrase -"
" this is probably a *bad* idea!\n\n"));
if( cpr_get_answer_is_yes("change_passwd.empty.okay",
_("Do you really want to do this? ")))
changed++;
break;
}
else { /* okay */
sk->protect.algo = dek->algo;
sk->protect.s2k = *s2k;
rc = protect_secret_key( sk, dek );
for(node=keyblock; !rc && node; node = node->next ) {
if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
PKT_secret_key *subsk = node->pkt->pkt.secret_key;
subsk->protect.algo = dek->algo;
subsk->protect.s2k = *s2k;
rc = protect_secret_key( subsk, dek );
}
}
if( rc )
log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
else
changed++;
break;
}
}
m_free(s2k);
m_free(dek);
}
leave:
m_free( passphrase );
set_next_passphrase( NULL );
return changed && !rc;
}
/****************
* There are some keys out (due to a bug in gnupg), where the sequence
* of the packets is wrong. This function fixes that.
* Returns: true if the keyblock has fixed.
*/
static int
fix_keyblock( KBNODE keyblock )
{
KBNODE node, last, subkey;
int fixed=0;
/* locate key signatures of class 0x10..0x13 behind sub key packets */
for( subkey=last=NULL, node = keyblock; node;
last=node, node = node->next ) {
switch( node->pkt->pkttype ) {
case PKT_PUBLIC_SUBKEY:
case PKT_SECRET_SUBKEY:
if( !subkey )
subkey = last; /* actually it is the one before the subkey */
break;
case PKT_SIGNATURE:
if( subkey ) {
PKT_signature *sig = node->pkt->pkt.signature;
if( sig->sig_class >= 0x10 && sig->sig_class <= 0x13 ) {
log_info(_(
"moving a key signature to the correct place\n"));
last->next = node->next;
node->next = subkey->next;
subkey->next = node;
node = last;
fixed=1;
}
}
break;
default: break;
}
}
return fixed;
}
/****************
* Menu driven key editor
*
* Note: to keep track of some selection we use node->mark MARKBIT_xxxx.
*/
void
keyedit_menu( const char *username, STRLIST locusr, STRLIST commands )
{
enum cmdids { cmdNONE = 0,
cmdQUIT, cmdHELP, cmdFPR, cmdLIST, cmdSELUID, cmdCHECK, cmdSIGN,
cmdDEBUG, cmdSAVE, cmdADDUID, cmdDELUID, cmdADDKEY, cmdDELKEY,
cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF, cmdEXPIRE,
cmdNOP };
static struct { const char *name;
enum cmdids id;
int need_sk;
const char *desc;
} cmds[] = {
{ N_("quit") , cmdQUIT , 0, N_("quit this menu") },
{ N_("q") , cmdQUIT , 0, NULL },
{ N_("save") , cmdSAVE , 0, N_("save and quit") },
{ N_("help") , cmdHELP , 0, N_("show this help") },
{ "?" , cmdHELP , 0, NULL },
{ N_("fpr") , cmdFPR , 0, N_("show fingerprint") },
{ N_("list") , cmdLIST , 0, N_("list key and user ids") },
{ N_("l") , cmdLIST , 0, NULL },
{ N_("uid") , cmdSELUID , 0, N_("select user id N") },
{ N_("key") , cmdSELKEY , 0, N_("select secondary key N") },
{ N_("check") , cmdCHECK , 0, N_("list signatures") },
{ N_("c") , cmdCHECK , 0, NULL },
{ N_("sign") , cmdSIGN , 0, N_("sign the key") },
{ N_("s") , cmdSIGN , 0, NULL },
{ N_("debug") , cmdDEBUG , 0, NULL },
{ N_("adduid") , cmdADDUID , 1, N_("add a user id") },
{ N_("deluid") , cmdDELUID , 0, N_("delete user id") },
{ N_("addkey") , cmdADDKEY , 1, N_("add a secondary key") },
{ N_("delkey") , cmdDELKEY , 0, N_("delete a secondary key") },
{ N_("expire") , cmdEXPIRE , 1, N_("change the expire date") },
{ N_("toggle") , cmdTOGGLE , 1, N_("toggle between secret "
"and public key listing") },
{ N_("t" ) , cmdTOGGLE , 1, NULL },
{ N_("pref") , cmdPREF , 0, N_("list preferences") },
{ N_("passwd") , cmdPASSWD , 1, N_("change the passphrase") },
{ N_("trust") , cmdTRUST , 0, N_("change the ownertrust") },
{ NULL, cmdNONE } };
enum cmdids cmd;
int rc = 0;
KBNODE keyblock = NULL;
KBPOS keyblockpos;
KBNODE sec_keyblock = NULL;
KBPOS sec_keyblockpos;
KBNODE cur_keyblock;
char *answer = NULL;
int redisplay = 1;
int modified = 0;
int sec_modified = 0;
int toggle;
int have_commands = !!commands;
if( opt.batch && !have_commands ) {
log_error(_("can't do that in batchmode\n"));
goto leave;
}
/* first try to locate it as secret key */
rc = find_secret_keyblock_byname( &sec_keyblockpos, username );
if( !rc ) {
rc = read_keyblock( &sec_keyblockpos, &sec_keyblock );
if( rc ) {
log_error("%s: secret keyblock read problem: %s\n",
username, g10_errstr(rc));
goto leave;
}
merge_keys_and_selfsig( sec_keyblock );
if( fix_keyblock( sec_keyblock ) )
sec_modified++;
}
/* and now get the public key */
rc = get_keyblock_byname( &keyblock, &keyblockpos, username );
if( rc )
goto leave;
if( fix_keyblock( keyblock ) )
modified++;
if( sec_keyblock ) { /* check that they match */
/* FIXME: check that they both match */
tty_printf(_("Secret key is available.\n"));
}
toggle = 0;
cur_keyblock = keyblock;
for(;;) { /* main loop */
int i, arg_number;
char *p;
tty_printf("\n");
if( redisplay ) {
show_key_with_all_names( cur_keyblock, 0, 0, 1, 0 );
tty_printf("\n");
redisplay = 0;
}
do {
m_free(answer);
if( have_commands ) {
if( commands ) {
answer = m_strdup( commands->d );
commands = commands->next;
}
else if( opt.batch ) {
answer = m_strdup("quit");
}
else
have_commands = 0;
}
if( !have_commands ) {
answer = cpr_get("keyedit.cmd", _("Command> "));
cpr_kill_prompt();
}
trim_spaces(answer);
} while( *answer == '#' );
arg_number = 0;
if( !*answer )
cmd = cmdLIST;
else if( *answer == CONTROL_D )
cmd = cmdQUIT;
else if( isdigit( *answer ) ) {
cmd = cmdSELUID;
arg_number = atoi(answer);
}
else {
if( (p=strchr(answer,' ')) ) {
*p++ = 0;
trim_spaces(answer);
trim_spaces(p);
arg_number = atoi(p);
}
for(i=0; cmds[i].name; i++ )
if( !stricmp( answer, cmds[i].name ) )
break;
if( cmds[i].need_sk && !sec_keyblock ) {
tty_printf(_("Need the secret key to do this.\n"));
cmd = cmdNOP;
}
else
cmd = cmds[i].id;
}
switch( cmd ) {
case cmdHELP:
for(i=0; cmds[i].name; i++ ) {
if( cmds[i].need_sk && !sec_keyblock )
; /* skip if we do not have the secret key */
else if( cmds[i].desc )
tty_printf("%-10s %s\n", cmds[i].name, _(cmds[i].desc) );
}
break;
case cmdQUIT:
if( have_commands )
goto leave;
if( !modified && !sec_modified )
goto leave;
if( !cpr_get_answer_is_yes("keyedit.save.okay",
_("Save changes? ")) ) {
if( cpr_enabled()
|| cpr_get_answer_is_yes("keyedit.cancel.okay",
_("Quit without saving? ")) )
goto leave;
break;
}
/* fall thru */
case cmdSAVE:
if( modified || sec_modified ) {
if( modified ) {
rc = update_keyblock( &keyblockpos, keyblock );
if( rc ) {
log_error(_("update failed: %s\n"), g10_errstr(rc) );
break;
}
}
if( sec_modified ) {
rc = update_keyblock( &sec_keyblockpos, sec_keyblock );
if( rc ) {
log_error(_("update secret failed: %s\n"),
g10_errstr(rc) );
break;
}
}
}
else
tty_printf(_("Key not changed so no update needed.\n"));
rc = update_trust_record( keyblock, 0, NULL );
if( rc )
log_error(_("update of trust db failed: %s\n"),
g10_errstr(rc) );
goto leave;
case cmdLIST:
redisplay = 1;
break;
case cmdFPR:
show_key_and_fingerprint( keyblock );
break;
case cmdSELUID:
if( menu_select_uid( cur_keyblock, arg_number ) )
redisplay = 1;
break;
case cmdSELKEY:
if( menu_select_key( cur_keyblock, arg_number ) )
redisplay = 1;
break;
case cmdCHECK:
/* we can only do this with the public key becuase the
* check functions can't cope with secret keys and it
* is questionable whether this would make sense at all */
check_all_keysigs( keyblock, count_selected_uids(keyblock) );
break;
case cmdSIGN: /* sign (only the public key) */
if( count_uids(keyblock) > 1 && !count_selected_uids(keyblock) ) {
if( !cpr_get_answer_is_yes("keyedit.sign_all.okay",
_("Really sign all user ids? ")) ) {
tty_printf(_("Hint: Select the user ids to sign\n"));
break;
}
}
sign_uids( keyblock, locusr, &modified );
break;
case cmdDEBUG:
dump_kbnode( cur_keyblock );
break;
case cmdTOGGLE:
toggle = !toggle;
cur_keyblock = toggle? sec_keyblock : keyblock;
redisplay = 1;
break;
case cmdADDUID:
if( menu_adduid( keyblock, sec_keyblock ) ) {
redisplay = 1;
sec_modified = modified = 1;
/* must update the trustdb already here, so that preferences
* get listed correctly */
rc = update_trust_record( keyblock, 0, NULL );
if( rc ) {
log_error(_("update of trust db failed: %s\n"),
g10_errstr(rc) );
rc = 0;
}
}
break;
case cmdDELUID: {
int n1;
if( !(n1=count_selected_uids(keyblock)) )
tty_printf(_("You must select at least one user id.\n"));
else if( count_uids(keyblock) - n1 < 1 )
tty_printf(_("You can't delete the last user id!\n"));
else if( cpr_get_answer_is_yes(
"keyedit.remove.uid.okay",
n1 > 1? _("Really remove all selected user ids? ")
: _("Really remove this user id? ")
) ) {
menu_deluid( keyblock, sec_keyblock );
redisplay = 1;
modified = 1;
if( sec_keyblock )
sec_modified = 1;
}
}
break;
case cmdADDKEY:
if( generate_subkeypair( keyblock, sec_keyblock ) ) {
redisplay = 1;
sec_modified = modified = 1;
}
break;
case cmdDELKEY: {
int n1;
if( !(n1=count_selected_keys( keyblock )) )
tty_printf(_("You must select at least one key.\n"));
else if( sec_keyblock && !cpr_get_answer_is_yes(
"keyedit.remove.subkey.okay",
n1 > 1?
_("Do you really want to delete the selected keys? "):
_("Do you really want to delete this key? ")
))
;
else {
menu_delkey( keyblock, sec_keyblock );
redisplay = 1;
modified = 1;
if( sec_keyblock )
sec_modified = 1;
}
}
break;
case cmdEXPIRE:
if( menu_expire( keyblock, sec_keyblock ) ) {
merge_keys_and_selfsig( sec_keyblock );
merge_keys_and_selfsig( keyblock );
sec_modified = 1;
modified = 1;
redisplay = 1;
}
break;
case cmdPASSWD:
if( change_passphrase( sec_keyblock ) )
sec_modified = 1;
break;
case cmdTRUST:
show_key_with_all_names( keyblock, 0, 0, 1, 0 );
tty_printf("\n");
if( edit_ownertrust( find_kbnode( keyblock,
PKT_PUBLIC_KEY )->pkt->pkt.public_key->local_id, 1 ) )
redisplay = 1;
/* we don't need to set modified here, as the trustvalues
* are updated immediately */
break;
case cmdPREF:
show_key_with_all_names( keyblock, 0, 0, 0, 1 );
break;
case cmdNOP:
break;
default:
tty_printf("\n");
tty_printf(_("Invalid command (try \"help\")\n"));
break;
}
} /* end main loop */
leave:
release_kbnode( keyblock );
release_kbnode( sec_keyblock );
m_free(answer);
}
/****************
* show preferences of a public keyblock.
*/
static void
show_prefs( KBNODE keyblock, PKT_user_id *uid )
{
KBNODE node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
PKT_public_key *pk;
byte *p;
int i;
size_t n;
byte namehash[20];
if( !node )
return; /* is a secret keyblock */
pk = node->pkt->pkt.public_key;
if( !pk->local_id ) {
log_error("oops: no LID\n");
return;
}
rmd160_hash_buffer( namehash, uid->name, uid->len );
p = get_pref_data( pk->local_id, namehash, &n );
if( !p )
return;
tty_printf(" ");
for(i=0; i < n; i+=2 ) {
if( p[i] )
tty_printf( " %c%d", p[i] == PREFTYPE_SYM ? 'S' :
p[i] == PREFTYPE_HASH ? 'H' :
p[i] == PREFTYPE_COMPR ? 'Z' : '?', p[i+1]);
}
tty_printf("\n");
m_free(p);
}
/****************
* Display the key a the user ids, if only_marked is true, do only
* so for user ids with mark A flag set and dont display the index number
*/
static void
show_key_with_all_names( KBNODE keyblock, int only_marked,
int with_fpr, int with_subkeys, int with_prefs )
{
KBNODE node;
int i;
/* the keys */
for( node = keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_PUBLIC_KEY
|| (with_subkeys && node->pkt->pkttype == PKT_PUBLIC_SUBKEY) ) {
PKT_public_key *pk = node->pkt->pkt.public_key;
int otrust=0, trust=0;
if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
/* do it here, so that debug messages don't clutter the
* output */
trust = query_trust_info(pk);
otrust = get_ownertrust_info( pk->local_id );
}
tty_printf("%s%c %4u%c/%08lX created: %s expires: %s",
node->pkt->pkttype == PKT_PUBLIC_KEY? "pub":"sub",
(node->flag & NODFLG_SELKEY)? '*':' ',
nbits_from_pk( pk ),
pubkey_letter( pk->pubkey_algo ),
(ulong)keyid_from_pk(pk,NULL),
datestr_from_pk(pk),
expirestr_from_pk(pk) );
if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
tty_printf(" trust: %c/%c", otrust, trust );
if( with_fpr ) {
tty_printf("\n");
show_fingerprint( pk );
}
}
tty_printf("\n");
}
else if( node->pkt->pkttype == PKT_SECRET_KEY
|| (with_subkeys && node->pkt->pkttype == PKT_SECRET_SUBKEY) ) {
PKT_secret_key *sk = node->pkt->pkt.secret_key;
tty_printf("%s%c %4u%c/%08lX created: %s expires: %s\n",
node->pkt->pkttype == PKT_SECRET_KEY? "sec":"sbb",
(node->flag & NODFLG_SELKEY)? '*':' ',
nbits_from_sk( sk ),
pubkey_letter( sk->pubkey_algo ),
(ulong)keyid_from_sk(sk,NULL),
datestr_from_sk(sk),
expirestr_from_sk(sk) );
}
}
/* the user ids */
i = 0;
for( node = keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID ) {
PKT_user_id *uid = node->pkt->pkt.user_id;
++i;
if( !only_marked || (only_marked && (node->flag & NODFLG_MARK_A))){
if( only_marked )
tty_printf(" ");
else if( node->flag & NODFLG_SELUID )
tty_printf("(%d)* ", i);
else
tty_printf("(%d) ", i);
tty_print_string( uid->name, uid->len );
tty_printf("\n");
if( with_prefs )
show_prefs( keyblock, uid );
}
}
}
}
static void
show_key_and_fingerprint( KBNODE keyblock )
{
KBNODE node;
PKT_public_key *pk = NULL;
for( node = keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
pk = node->pkt->pkt.public_key;
tty_printf("pub %4u%c/%08lX %s ",
nbits_from_pk( pk ),
pubkey_letter( pk->pubkey_algo ),
(ulong)keyid_from_pk(pk,NULL),
datestr_from_pk(pk) );
}
else if( node->pkt->pkttype == PKT_USER_ID ) {
PKT_user_id *uid = node->pkt->pkt.user_id;
tty_print_string( uid->name, uid->len );
break;
}
}
tty_printf("\n");
if( pk )
show_fingerprint( pk );
}
static void
show_fingerprint( PKT_public_key *pk )
{
byte array[MAX_FINGERPRINT_LEN], *p;
size_t i, n;
fingerprint_from_pk( pk, array, &n );
p = array;
tty_printf(" Fingerprint:");
if( n == 20 ) {
for(i=0; i < n ; i++, i++, p += 2 ) {
if( i == 10 )
tty_printf(" ");
tty_printf(" %02X%02X", *p, p[1] );
}
}
else {
for(i=0; i < n ; i++, p++ ) {
if( i && !(i%8) )
tty_printf(" ");
tty_printf(" %02X", *p );
}
}
tty_printf("\n");
}
/****************
* Ask for a new user id , do the selfsignature and put it into
* both keyblocks.
* Return true if there is a new user id
*/
static int
menu_adduid( KBNODE pub_keyblock, KBNODE sec_keyblock )
{
PKT_user_id *uid;
PKT_public_key *pk=NULL;
PKT_secret_key *sk=NULL;
PKT_signature *sig=NULL;
PACKET *pkt;
KBNODE node;
KBNODE pub_where=NULL, sec_where=NULL;
int rc;
uid = generate_user_id();
if( !uid )
return 0;
for( node = pub_keyblock; node; pub_where = node, node = node->next ) {
if( node->pkt->pkttype == PKT_PUBLIC_KEY )
pk = node->pkt->pkt.public_key;
else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
break;
}
if( !node ) /* no subkey */
pub_where = NULL;
for( node = sec_keyblock; node; sec_where = node, node = node->next ) {
if( node->pkt->pkttype == PKT_SECRET_KEY )
sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
else if( node->pkt->pkttype == PKT_SECRET_SUBKEY )
break;
}
if( !node ) /* no subkey */
sec_where = NULL;
assert(pk && sk );
rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0,
keygen_add_std_prefs, pk );
free_secret_key( sk );
if( rc ) {
log_error("signing failed: %s\n", g10_errstr(rc) );
free_user_id(uid);
return 0;
}
/* insert/append to secret keyblock */
pkt = m_alloc_clear( sizeof *pkt );
pkt->pkttype = PKT_USER_ID;
pkt->pkt.user_id = copy_user_id(NULL, uid);
node = new_kbnode(pkt);
if( sec_where )
insert_kbnode( sec_where, node, 0 );
else
add_kbnode( sec_keyblock, node );
pkt = m_alloc_clear( sizeof *pkt );
pkt->pkttype = PKT_SIGNATURE;
pkt->pkt.signature = copy_signature(NULL, sig);
if( sec_where )
insert_kbnode( node, new_kbnode(pkt), 0 );
else
add_kbnode( sec_keyblock, new_kbnode(pkt) );
/* insert/append to public keyblock */
pkt = m_alloc_clear( sizeof *pkt );
pkt->pkttype = PKT_USER_ID;
pkt->pkt.user_id = uid;
node = new_kbnode(pkt);
if( pub_where )
insert_kbnode( pub_where, node, 0 );
else
add_kbnode( pub_keyblock, node );
pkt = m_alloc_clear( sizeof *pkt );
pkt->pkttype = PKT_SIGNATURE;
pkt->pkt.signature = copy_signature(NULL, sig);
if( pub_where )
insert_kbnode( node, new_kbnode(pkt), 0 );
else
add_kbnode( pub_keyblock, new_kbnode(pkt) );
return 1;
}
/****************
* Remove all selceted userids from the keyrings
*/
static void
menu_deluid( KBNODE pub_keyblock, KBNODE sec_keyblock )
{
KBNODE node;
int selected=0;
for( node = pub_keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID ) {
selected = node->flag & NODFLG_SELUID;
if( selected ) {
delete_kbnode( node );
if( sec_keyblock ) {
KBNODE snode;
int s_selected = 0;
PKT_user_id *uid = node->pkt->pkt.user_id;
for( snode = sec_keyblock; snode; snode = snode->next ) {
if( snode->pkt->pkttype == PKT_USER_ID ) {
PKT_user_id *suid = snode->pkt->pkt.user_id;
s_selected =
(uid->len == suid->len
&& !memcmp( uid->name, suid->name, uid->len));
if( s_selected )
delete_kbnode( snode );
}
else if( s_selected
&& snode->pkt->pkttype == PKT_SIGNATURE )
delete_kbnode( snode );
else if( snode->pkt->pkttype == PKT_SECRET_SUBKEY )
s_selected = 0;
}
}
}
}
else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
delete_kbnode( node );
else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
selected = 0;
}
commit_kbnode( &pub_keyblock );
if( sec_keyblock )
commit_kbnode( &sec_keyblock );
}
/****************
* Remove some of the secondary keys
*/
static void
menu_delkey( KBNODE pub_keyblock, KBNODE sec_keyblock )
{
KBNODE node;
int selected=0;
for( node = pub_keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
selected = node->flag & NODFLG_SELKEY;
if( selected ) {
delete_kbnode( node );
if( sec_keyblock ) {
KBNODE snode;
int s_selected = 0;
u32 ki[2];
keyid_from_pk( node->pkt->pkt.public_key, ki );
for( snode = sec_keyblock; snode; snode = snode->next ) {
if( snode->pkt->pkttype == PKT_SECRET_SUBKEY ) {
u32 ki2[2];
keyid_from_sk( snode->pkt->pkt.secret_key, ki2 );
s_selected = (ki[0] == ki2[0] && ki[1] == ki2[1]);
if( s_selected )
delete_kbnode( snode );
}
else if( s_selected
&& snode->pkt->pkttype == PKT_SIGNATURE )
delete_kbnode( snode );
else
s_selected = 0;
}
}
}
}
else if( selected && node->pkt->pkttype == PKT_SIGNATURE )
delete_kbnode( node );
else
selected = 0;
}
commit_kbnode( &pub_keyblock );
if( sec_keyblock )
commit_kbnode( &sec_keyblock );
}
static int
menu_expire( KBNODE pub_keyblock, KBNODE sec_keyblock )
{
int n1, signumber, rc;
u32 expiredate;
int mainkey=0;
PKT_secret_key *sk; /* copy of the main sk */
PKT_public_key *main_pk, *sub_pk;
PKT_user_id *uid;
KBNODE node;
u32 keyid[2];
if( count_selected_keys( sec_keyblock ) ) {
tty_printf(_("Please remove selections from the secret keys.\n"));
return 0;
}
n1 = count_selected_keys( pub_keyblock );
if( n1 > 1 ) {
tty_printf(_("Please select at most one secondary key.\n"));
return 0;
}
else if( n1 )
tty_printf(_("Changing exiration time for a secondary key.\n"));
else {
tty_printf(_("Changing exiration time for the primary key.\n"));
mainkey=1;
}
expiredate = ask_expiredate();
node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
sk = copy_secret_key( NULL, node->pkt->pkt.secret_key);
/* Now we can actually change the self signature(s) */
main_pk = sub_pk = NULL;
uid = NULL;
signumber = 0;
for( node=pub_keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_PUBLIC_KEY ) {
main_pk = node->pkt->pkt.public_key;
keyid_from_pk( main_pk, keyid );
main_pk->expiredate = expiredate;
}
else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
&& (node->flag & NODFLG_SELKEY ) ) {
sub_pk = node->pkt->pkt.public_key;
sub_pk->expiredate = expiredate;
}
else if( node->pkt->pkttype == PKT_USER_ID )
uid = node->pkt->pkt.user_id;
else if( main_pk && node->pkt->pkttype == PKT_SIGNATURE ) {
PKT_signature *sig = node->pkt->pkt.signature;
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
&& ( (mainkey && uid && (sig->sig_class&~3) == 0x10)
|| (!mainkey && sig->sig_class == 0x18) ) ) {
/* this is a selfsignature which is to be replaced */
PKT_signature *newsig;
PACKET *newpkt;
KBNODE sn;
int signumber2 = 0;
signumber++;
if( (mainkey && main_pk->version < 4)
|| (!mainkey && sub_pk->version < 4 ) ) {
log_info(_(
"You can't change the expiration date of a v3 key\n"));
free_secret_key( sk );
return 0;
}
/* find the corresponding secret self-signature */
for( sn=sec_keyblock; sn; sn = sn->next ) {
if( sn->pkt->pkttype == PKT_SIGNATURE ) {
PKT_signature *b = sn->pkt->pkt.signature;
if( keyid[0] == b->keyid[0] && keyid[1] == b->keyid[1]
&& sig->sig_class == b->sig_class
&& ++signumber2 == signumber )
break;
}
}
if( !sn )
log_info(_("No corresponding signature in secret ring\n"));
/* create new self signature */
if( mainkey )
rc = make_keysig_packet( &newsig, main_pk, uid, NULL,
sk, 0x13, 0,
keygen_add_std_prefs, main_pk );
else
rc = make_keysig_packet( &newsig, main_pk, NULL, sub_pk,
sk, 0x18, 0,
keygen_add_key_expire, sub_pk );
if( rc ) {
log_error("make_keysig_packet failed: %s\n",
g10_errstr(rc));
free_secret_key( sk );
return 0;
}
/* replace the packet */
newpkt = m_alloc_clear( sizeof *newpkt );
newpkt->pkttype = PKT_SIGNATURE;
newpkt->pkt.signature = newsig;
free_packet( node->pkt );
m_free( node->pkt );
node->pkt = newpkt;
if( sn ) {
newpkt = m_alloc_clear( sizeof *newpkt );
newpkt->pkttype = PKT_SIGNATURE;
newpkt->pkt.signature = copy_signature( NULL, newsig );
free_packet( sn->pkt );
m_free( sn->pkt );
sn->pkt = newpkt;
}
}
}
}
free_secret_key( sk );
return 1;
}
/****************
* Select one user id or remove all selection if index is 0.
* Returns: True if the selection changed;
*/
static int
menu_select_uid( KBNODE keyblock, int index )
{
KBNODE node;
int i;
/* first check that the index is valid */
if( index ) {
for( i=0, node = keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID ) {
if( ++i == index )
break;
}
}
if( !node ) {
tty_printf(_("No user id with index %d\n"), index );
return 0;
}
}
else { /* reset all */
for( i=0, node = keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID )
node->flag &= ~NODFLG_SELUID;
}
return 1;
}
/* and toggle the new index */
for( i=0, node = keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID ) {
if( ++i == index )
if( (node->flag & NODFLG_SELUID) )
node->flag &= ~NODFLG_SELUID;
else
node->flag |= NODFLG_SELUID;
}
}
return 1;
}
/****************
* Select secondary keys
* Returns: True if the selection changed;
*/
static int
menu_select_key( KBNODE keyblock, int index )
{
KBNODE node;
int i;
/* first check that the index is valid */
if( index ) {
for( i=0, node = keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
if( ++i == index )
break;
}
}
if( !node ) {
tty_printf(_("No secondary key with index %d\n"), index );
return 0;
}
}
else { /* reset all */
for( i=0, node = keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype == PKT_SECRET_SUBKEY )
node->flag &= ~NODFLG_SELKEY;
}
return 1;
}
/* and set the new index */
for( i=0, node = keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
if( ++i == index )
if( (node->flag & NODFLG_SELKEY) )
node->flag &= ~NODFLG_SELKEY;
else
node->flag |= NODFLG_SELKEY;
}
}
return 1;
}
static int
count_uids_with_flag( KBNODE keyblock, unsigned flag )
{
KBNODE node;
int i=0;
for( node = keyblock; node; node = node->next )
if( node->pkt->pkttype == PKT_USER_ID && (node->flag & flag) )
i++;
return i;
}
static int
count_keys_with_flag( KBNODE keyblock, unsigned flag )
{
KBNODE node;
int i=0;
for( node = keyblock; node; node = node->next )
if( ( node->pkt->pkttype == PKT_PUBLIC_SUBKEY
|| node->pkt->pkttype == PKT_SECRET_SUBKEY)
&& (node->flag & flag) )
i++;
return i;
}
static int
count_uids( KBNODE keyblock )
{
KBNODE node;
int i=0;
for( node = keyblock; node; node = node->next )
if( node->pkt->pkttype == PKT_USER_ID )
i++;
return i;
}
/****************
* Returns true if there is at least one selected user id
*/
static int
count_selected_uids( KBNODE keyblock )
{
return count_uids_with_flag( keyblock, NODFLG_SELUID);
}
static int
count_selected_keys( KBNODE keyblock )
{
return count_keys_with_flag( keyblock, NODFLG_SELKEY);
}
diff --git a/g10/keygen.c b/g10/keygen.c
index cea7ffdb5..2745649c5 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -1,1039 +1,1039 @@
/* keygen.c - generate a key pair
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <ctype.h>
#include <errno.h>
#include <assert.h>
#include "util.h"
#include "main.h"
#include "packet.h"
#include "cipher.h"
#include "ttyio.h"
#include "options.h"
#include "keydb.h"
#include "status.h"
#include "i18n.h"
static void
write_uid( KBNODE root, const char *s )
{
PACKET *pkt = m_alloc_clear(sizeof *pkt );
size_t n = strlen(s);
pkt->pkttype = PKT_USER_ID;
pkt->pkt.user_id = m_alloc( sizeof *pkt->pkt.user_id + n - 1 );
pkt->pkt.user_id->len = n;
strcpy(pkt->pkt.user_id->name, s);
add_kbnode( root, new_kbnode( pkt ) );
}
int
keygen_add_key_expire( PKT_signature *sig, void *opaque )
{
PKT_public_key *pk = opaque;
byte buf[8];
u32 u;
if( pk->expiredate ) {
u = pk->expiredate > pk->timestamp? pk->expiredate - pk->timestamp
: pk->timestamp;
buf[0] = (u >> 24) & 0xff;
buf[1] = (u >> 16) & 0xff;
buf[2] = (u >> 8) & 0xff;
buf[3] = u & 0xff;
build_sig_subpkt( sig, SIGSUBPKT_KEY_EXPIRE, buf, 4 );
}
return 0;
}
/****************
* Add preference to the self signature packet.
* This is only called for packets with version > 3.
*/
int
keygen_add_std_prefs( PKT_signature *sig, void *opaque )
{
byte buf[8];
keygen_add_key_expire( sig, opaque );
buf[0] = CIPHER_ALGO_BLOWFISH;
buf[1] = CIPHER_ALGO_CAST5;
build_sig_subpkt( sig, SIGSUBPKT_PREF_SYM, buf, 2 );
buf[0] = DIGEST_ALGO_RMD160;
buf[1] = DIGEST_ALGO_SHA1;
buf[2] = DIGEST_ALGO_TIGER;
buf[3] = DIGEST_ALGO_MD5;
build_sig_subpkt( sig, SIGSUBPKT_PREF_HASH, buf, 4 );
buf[0] = 2;
buf[1] = 1;
build_sig_subpkt( sig, SIGSUBPKT_PREF_COMPR, buf, 2 );
buf[0] = 0x80; /* no modify - It is reasonable that a key holder
* has the possibility to reject signatures from users
* who are known to sign everything without any
* validation - so a signed key should be send
* to the holder who in turn can put it on a keyserver
*/
build_sig_subpkt( sig, SIGSUBPKT_KS_FLAGS, buf, 1 );
return 0;
}
static int
write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk )
{
PACKET *pkt;
PKT_signature *sig;
PKT_user_id *uid;
int rc=0;
KBNODE node;
PKT_public_key *pk;
if( opt.verbose )
log_info(_("writing self signature\n"));
/* get the uid packet from the list */
node = find_kbnode( root, PKT_USER_ID );
if( !node )
BUG(); /* no user id packet in tree */
uid = node->pkt->pkt.user_id;
/* get the pk packet from the pub_tree */
node = find_kbnode( pub_root, PKT_PUBLIC_KEY );
if( !node )
BUG();
pk = node->pkt->pkt.public_key;
/* and make the signature */
rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0,
keygen_add_std_prefs, pk );
if( rc ) {
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
return rc;
}
pkt = m_alloc_clear( sizeof *pkt );
pkt->pkttype = PKT_SIGNATURE;
pkt->pkt.signature = sig;
add_kbnode( root, new_kbnode( pkt ) );
return rc;
}
static int
write_keybinding( KBNODE root, KBNODE pub_root, PKT_secret_key *sk )
{
PACKET *pkt;
PKT_signature *sig;
int rc=0;
KBNODE node;
PKT_public_key *pk, *subpk;
if( opt.verbose )
log_info(_("writing key binding signature\n"));
/* get the pk packet from the pub_tree */
node = find_kbnode( pub_root, PKT_PUBLIC_KEY );
if( !node )
BUG();
pk = node->pkt->pkt.public_key;
/* find the last subkey */
subpk = NULL;
for(node=pub_root; node; node = node->next ) {
if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
subpk = node->pkt->pkt.public_key;
}
if( !subpk )
BUG();
/* and make the signature */
rc = make_keysig_packet( &sig, pk, NULL, subpk, sk, 0x18, 0,
keygen_add_key_expire, subpk );
if( rc ) {
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
return rc;
}
pkt = m_alloc_clear( sizeof *pkt );
pkt->pkttype = PKT_SIGNATURE;
pkt->pkt.signature = sig;
add_kbnode( root, new_kbnode( pkt ) );
return rc;
}
static int
gen_elg(int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval,
int version )
{
int rc;
int i;
PACKET *pkt;
PKT_secret_key *sk;
PKT_public_key *pk;
MPI skey[4];
MPI *factors;
assert( is_ELGAMAL(algo) );
rc = pubkey_generate( algo, nbits, skey, &factors );
if( rc ) {
log_error("pubkey_generate failed: %s\n", g10_errstr(rc) );
return rc;
}
sk = m_alloc_clear( sizeof *sk );
pk = m_alloc_clear( sizeof *pk );
sk->timestamp = pk->timestamp = make_timestamp();
sk->version = pk->version = version;
if( expireval ) {
sk->expiredate = pk->expiredate = sk->timestamp + expireval;
}
sk->pubkey_algo = pk->pubkey_algo = algo;
pk->pkey[0] = mpi_copy( skey[0] );
pk->pkey[1] = mpi_copy( skey[1] );
pk->pkey[2] = mpi_copy( skey[2] );
sk->skey[0] = skey[0];
sk->skey[1] = skey[1];
sk->skey[2] = skey[2];
sk->skey[3] = skey[3];
sk->is_protected = 0;
sk->protect.algo = 0;
sk->csum = checksum_mpi_counted_nbits( sk->skey[3] );
if( ret_sk ) /* not a subkey: return an unprotected version of the sk */
*ret_sk = copy_secret_key( NULL, sk );
if( dek ) {
sk->protect.algo = dek->algo;
sk->protect.s2k = *s2k;
rc = protect_secret_key( sk, dek );
if( rc ) {
log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
free_public_key(pk);
free_secret_key(sk);
return rc;
}
}
pkt = m_alloc_clear(sizeof *pkt);
pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY;
pkt->pkt.public_key = pk;
add_kbnode(pub_root, new_kbnode( pkt ));
/* don't know whether it makes sense to have the factors, so for now
* we store them in the secret keyring (but they are not secret) */
pkt = m_alloc_clear(sizeof *pkt);
pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY;
pkt->pkt.secret_key = sk;
add_kbnode(sec_root, new_kbnode( pkt ));
for(i=0; factors[i]; i++ )
add_kbnode( sec_root,
make_mpi_comment_node("#:ELG_factor:", factors[i] ));
return 0;
}
/****************
* Generate a DSA key
*/
static int
gen_dsa(unsigned nbits, KBNODE pub_root, KBNODE sec_root, DEK *dek,
STRING2KEY *s2k, PKT_secret_key **ret_sk, u32 expireval )
{
int rc;
int i;
PACKET *pkt;
PKT_secret_key *sk;
PKT_public_key *pk;
MPI skey[5];
MPI *factors;
if( nbits > 1024 )
nbits = 1024;
rc = pubkey_generate( PUBKEY_ALGO_DSA, nbits, skey, &factors );
if( rc ) {
log_error("pubkey_generate failed: %s\n", g10_errstr(rc) );
return rc;
}
sk = m_alloc_clear( sizeof *sk );
pk = m_alloc_clear( sizeof *pk );
sk->timestamp = pk->timestamp = make_timestamp();
sk->version = pk->version = 4;
if( expireval ) {
sk->expiredate = pk->expiredate = sk->timestamp + expireval;
}
sk->pubkey_algo = pk->pubkey_algo = PUBKEY_ALGO_DSA;
pk->pkey[0] = mpi_copy( skey[0] );
pk->pkey[1] = mpi_copy( skey[1] );
pk->pkey[2] = mpi_copy( skey[2] );
pk->pkey[3] = mpi_copy( skey[3] );
sk->skey[0] = skey[0];
sk->skey[1] = skey[1];
sk->skey[2] = skey[2];
sk->skey[3] = skey[3];
sk->skey[4] = skey[4];
sk->is_protected = 0;
sk->protect.algo = 0;
sk->csum = checksum_mpi_counted_nbits( sk->skey[4] );
if( ret_sk ) /* not a subkey: return an unprotected version of the sk */
*ret_sk = copy_secret_key( NULL, sk );
if( dek ) {
sk->protect.algo = dek->algo;
sk->protect.s2k = *s2k;
rc = protect_secret_key( sk, dek );
if( rc ) {
log_error("protect_secret_key failed: %s\n", g10_errstr(rc) );
free_public_key(pk);
free_secret_key(sk);
return rc;
}
}
pkt = m_alloc_clear(sizeof *pkt);
pkt->pkttype = ret_sk ? PKT_PUBLIC_KEY : PKT_PUBLIC_SUBKEY;
pkt->pkt.public_key = pk;
add_kbnode(pub_root, new_kbnode( pkt ));
/* don't know whether it makes sense to have the factors, so for now
* we store them in the secret keyring (but they are not secret)
* p = 2 * q * f1 * f2 * ... * fn
* We store only f1 to f_n-1; fn can be calculated because p and q
* are known.
*/
pkt = m_alloc_clear(sizeof *pkt);
pkt->pkttype = ret_sk ? PKT_SECRET_KEY : PKT_SECRET_SUBKEY;
pkt->pkt.secret_key = sk;
add_kbnode(sec_root, new_kbnode( pkt ));
for(i=1; factors[i]; i++ ) /* the first one is q */
add_kbnode( sec_root,
make_mpi_comment_node("#:DSA_factor:", factors[i] ));
return 0;
}
/****************
* check valid days:
* return 0 on error or the multiplier
*/
static int
check_valid_days( const char *s )
{
if( !isdigit(*s) )
return 0;
for( s++; *s; s++)
if( !isdigit(*s) )
break;
if( !*s )
return 1;
if( s[1] )
return 0; /* e.g. "2323wc" */
if( *s == 'd' || *s == 'D' )
return 1;
if( *s == 'w' || *s == 'W' )
return 7;
if( *s == 'm' || *s == 'M' )
return 30;
if( *s == 'y' || *s == 'Y' )
return 365;
return 0;
}
/****************
* Returns: 0 to create both a DSA and a ElGamal key.
*/
static int
ask_algo( int *ret_v4, int addmode )
{
char *answer;
int algo;
tty_printf(_("Please select what kind of key you want:\n"));
if( !addmode )
tty_printf(_(" (%d) DSA and ElGamal (default)\n"), 1 );
tty_printf( _(" (%d) DSA (sign only)\n"), 2 );
if( addmode )
tty_printf( _(" (%d) ElGamal (encrypt only)\n"), 3 );
tty_printf( _(" (%d) ElGamal (sign and encrypt)\n"), 4 );
#if 0
tty_printf( _(" (%d) ElGamal in a v3 packet\n"), 5 );
#endif
*ret_v4 = 1;
for(;;) {
answer = cpr_get("keygen.algo",_("Your selection? "));
cpr_kill_prompt();
algo = *answer? atoi(answer): 1;
m_free(answer);
if( algo == 1 && !addmode ) {
algo = 0; /* create both keys */
break;
}
else if( algo == 4 ) {
if( cpr_get_answer_is_yes("keygen.algo.elg_se",_(
"Do you really want to create a sign and encrypt key? "))) {
algo = PUBKEY_ALGO_ELGAMAL;
break;
}
}
else if( algo == 3 && addmode ) {
algo = PUBKEY_ALGO_ELGAMAL_E;
break;
}
else if( algo == 2 ) {
algo = PUBKEY_ALGO_DSA;
break;
}
#if 0
else if( algo == 5 ) {
algo = PUBKEY_ALGO_ELGAMAL_E;
*ret_v4 = 0;
break;
}
#endif
else
tty_printf(_("Invalid selection.\n"));
}
return algo;
}
static unsigned
ask_keysize( int algo )
{
char *answer;
unsigned nbits;
tty_printf(_("About to generate a new %s keypair.\n"
" minimum keysize is 768 bits\n"
" default keysize is 1024 bits\n"
" highest suggested keysize is 2048 bits\n"),
pubkey_algo_to_string(algo) );
for(;;) {
answer = cpr_get("keygen.size",
_("What keysize do you want? (1024) "));
cpr_kill_prompt();
nbits = *answer? atoi(answer): 1024;
m_free(answer);
if( algo == PUBKEY_ALGO_DSA && (nbits < 512 || nbits > 1024) )
tty_printf(_("DSA only allows keysizes from 512 to 1024\n"));
else if( nbits < 768 )
tty_printf(_("keysize too small; 768 is smallest value allowed.\n"));
else if( nbits > 2048 && !cpr_enabled() ) {
tty_printf(
_("Keysizes larger than 2048 are not suggested because\n"
"computations take REALLY long!\n"));
if( cpr_get_answer_is_yes("keygen.size.huge.okay",_(
"Are you sure that you want this keysize? ")) ) {
tty_printf(_("Okay, but keep in mind that your monitor "
"and keyboard radiation is also very vulnerable "
"to attacks!\n"));
break;
}
}
else if( nbits > 1536 && !cpr_enabled() ) {
if( cpr_get_answer_is_yes("keygen.size.large.okay",_(
"Do you really need such a large keysize? ")) )
break;
}
else
break;
}
tty_printf(_("Requested keysize is %u bits\n"), nbits );
if( algo == PUBKEY_ALGO_DSA && (nbits % 64) ) {
nbits = ((nbits + 63) / 64) * 64;
tty_printf(_("rounded up to %u bits\n"), nbits );
}
else if( (nbits % 32) ) {
nbits = ((nbits + 31) / 32) * 32;
tty_printf(_("rounded up to %u bits\n"), nbits );
}
return nbits;
}
static u32
ask_expire_interval()
{
char *answer;
int valid_days=0;
u32 interval = 0;
tty_printf(_("Please specify how long the key should be valid.\n"
" 0 = key does not expire\n"
" <n> = key expires in n days\n"
" <n>w = key expires in n weeks\n"
" <n>m = key expires in n months\n"
" <n>y = key expires in n years\n"));
/* Note: The elgamal subkey for DSA has no expiration date because
* it must be signed with the DSA key and this one has the expiration
* date */
answer = NULL;
for(;;) {
int mult;
m_free(answer);
answer = cpr_get("keygen.valid",_("Key is valid for? (0) "));
cpr_kill_prompt();
trim_spaces(answer);
if( !*answer )
valid_days = 0;
else if( (mult=check_valid_days(answer)) ) {
valid_days = atoi(answer) * mult;
if( valid_days < 0 || valid_days > 32767 )
valid_days = 0;
}
else {
tty_printf(_("invalid value\n"));
continue;
}
if( !valid_days ) {
tty_printf(_("Key does not expire at all\n"));
interval = 0;
}
else {
interval = valid_days * 86400L;
/* print the date when the key expires */
tty_printf(_("Key expires at %s\n"),
asctimestamp(make_timestamp() + interval ) );
}
if( !cpr_enabled()
&& cpr_get_answer_is_yes("keygen.valid.okay",
_("Is this correct (y/n)? ")) )
break;
}
m_free(answer);
return interval;
}
u32
ask_expiredate()
{
u32 x = ask_expire_interval();
return x? make_timestamp() + x : 0;
}
static int
has_invalid_email_chars( const char *s )
{
int at_seen=0;
for( ; *s; s++ ) {
if( *s & 0x80 )
return 1;
if( *s == '@' )
at_seen=1;
else if( !at_seen
&& !strchr("01234567890abcdefghijklmnopqrstuvwxyz_-.+", *s ))
return 1;
else if( at_seen
&& !strchr("01234567890abcdefghijklmnopqrstuvwxyz_-.", *s ) )
return 1;
}
return 0;
}
static char *
ask_user_id( int mode )
{
char *answer;
char *aname, *acomment, *amail, *uid;
if( !mode )
tty_printf( _("\n"
"You need a User-ID to identify your key; the software constructs the user id\n"
"from Real Name, Comment and Email Address in this form:\n"
" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n\n") );
uid = aname = acomment = amail = NULL;
for(;;) {
char *p;
if( !aname ) {
for(;;) {
m_free(aname);
aname = cpr_get("keygen.name",_("Real name: "));
trim_spaces(aname);
cpr_kill_prompt();
if( strpbrk( aname, "<([])>" ) )
tty_printf(_("Invalid character in name\n"));
else if( isdigit(*aname) )
tty_printf(_("Name may not start with a digit\n"));
else if( strlen(aname) < 5 )
tty_printf(_("Name must be at least 5 characters long\n"));
else
break;
}
}
if( !amail ) {
for(;;) {
m_free(amail);
amail = cpr_get("keygen.email",_("Email address: "));
trim_spaces(amail);
strlwr(amail);
cpr_kill_prompt();
if( !*amail )
break; /* no email address is okay */
else if( has_invalid_email_chars(amail)
|| string_count_chr(amail,'@') != 1
|| *amail == '@'
|| amail[strlen(amail)-1] == '@'
|| amail[strlen(amail)-1] == '.'
|| strstr(amail, "..") )
tty_printf(_("Not a valid email address\n"));
else
break;
}
}
if( !acomment ) {
for(;;) {
m_free(acomment);
acomment = cpr_get("keygen.comment",_("Comment: "));
trim_spaces(acomment);
cpr_kill_prompt();
if( !*acomment )
break; /* no comment is okay */
else if( strpbrk( acomment, "()" ) )
tty_printf(_("Invalid character in comment\n"));
else
break;
}
}
m_free(uid);
uid = p = m_alloc(strlen(aname)+strlen(amail)+strlen(acomment)+12+10);
p = stpcpy(p, aname );
if( *acomment )
p = stpcpy(stpcpy(stpcpy(p," ("), acomment),")");
if( *amail )
p = stpcpy(stpcpy(stpcpy(p," <"), amail),">");
/* append a warning if we do not have dev/random
* or it is switched into quick testmode */
if( quick_random_gen(-1) )
strcpy(p, " (INSECURE!)" );
tty_printf(_("You selected this USER-ID:\n \"%s\"\n\n"), uid);
/* fixme: add a warning if this user-id already exists */
for(;;) {
char *ansstr = _("NnCcEeOoQq");
if( strlen(ansstr) != 10 )
BUG();
if( cpr_enabled() ) {
answer = m_strdup(ansstr+6);
answer[1] = 0;
}
else {
answer = cpr_get("keygen.userid.cmd",_(
"Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? "));
cpr_kill_prompt();
}
if( strlen(answer) > 1 )
;
else if( *answer == ansstr[0] || *answer == ansstr[1] ) {
m_free(aname); aname = NULL;
break;
}
else if( *answer == ansstr[2] || *answer == ansstr[3] ) {
m_free(acomment); acomment = NULL;
break;
}
else if( *answer == ansstr[4] || *answer == ansstr[5] ) {
m_free(amail); amail = NULL;
break;
}
else if( *answer == ansstr[6] || *answer == ansstr[7] ) {
m_free(aname); aname = NULL;
m_free(acomment); acomment = NULL;
m_free(amail); amail = NULL;
break;
}
else if( *answer == ansstr[8] || *answer == ansstr[9] ) {
m_free(aname); aname = NULL;
m_free(acomment); acomment = NULL;
m_free(amail); amail = NULL;
m_free(uid); uid = NULL;
break;
}
m_free(answer);
}
m_free(answer);
if( !amail && !acomment && !amail )
break;
m_free(uid); uid = NULL;
}
if( uid ) {
char *p = native_to_utf8( uid );
m_free( uid );
uid = p;
}
return uid;
}
static DEK *
ask_passphrase( STRING2KEY **ret_s2k )
{
DEK *dek = NULL;
STRING2KEY *s2k;
tty_printf(_("You need a Passphrase to protect your secret key.\n\n") );
s2k = m_alloc_secure( sizeof *s2k );
for(;;) {
s2k->mode = opt.s2k_mode;
s2k->hash_algo = opt.s2k_digest_algo;
dek = passphrase_to_dek( NULL, opt.s2k_cipher_algo, s2k, 2 );
if( !dek ) {
tty_printf(_("passphrase not correctly repeated; try again.\n"));
}
else if( !dek->keylen ) {
m_free(dek); dek = NULL;
m_free(s2k); s2k = NULL;
tty_printf(_(
"You don't want a passphrase - this is probably a *bad* idea!\n"
"I will do it anyway. You can change your passphrase at any time,\n"
"using this program with the option \"--edit-key\".\n\n"));
break;
}
else
break; /* okay */
}
*ret_s2k = s2k;
return dek;
}
static int
do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root,
DEK *dek, STRING2KEY *s2k, PKT_secret_key **sk, u32 expiredate,
int v4_packet )
{
int rc=0;
tty_printf(_(
"We need to generate a lot of random bytes. It is a good idea to perform\n"
"some other action (work in another window, move the mouse, utilize the\n"
"network and the disks) during the prime generation; this gives the random\n"
"number generator a better chance to gain enough entropy.\n") );
if( algo == PUBKEY_ALGO_ELGAMAL || algo == PUBKEY_ALGO_ELGAMAL_E )
rc = gen_elg(algo, nbits, pub_root, sec_root, dek, s2k,
sk, expiredate, v4_packet? 4:3 );
else if( algo == PUBKEY_ALGO_DSA )
rc = gen_dsa(nbits, pub_root, sec_root, dek, s2k, sk, expiredate);
else
BUG();
#ifdef ENABLE_COMMENT_PACKETS
if( !rc ) {
add_kbnode( pub_root,
make_comment_node("#created by GNUPG v" VERSION " ("
PRINTABLE_OS_NAME ")"));
add_kbnode( sec_root,
make_comment_node("#created by GNUPG v" VERSION " ("
PRINTABLE_OS_NAME ")"));
}
#endif
return rc;
}
/****************
* Generate a new user id packet, or return NULL if cancelled
*/
PKT_user_id *
generate_user_id()
{
PKT_user_id *uid;
char *p;
size_t n;
p = ask_user_id( 1 );
if( !p )
return NULL;
n = strlen(p);
uid = m_alloc( sizeof *uid + n - 1 );
uid->len = n;
strcpy(uid->name, p);
return uid;
}
/****************
* Generate a keypair
*/
void
generate_keypair()
{
unsigned nbits;
char *pub_fname = NULL;
char *sec_fname = NULL;
char *uid = NULL;
KBNODE pub_root = NULL;
KBNODE sec_root = NULL;
PKT_secret_key *sk = NULL;
DEK *dek;
STRING2KEY *s2k;
int rc;
int algo;
u32 expire;
int v4;
int both = 0;
if( opt.batch || opt.answer_yes || opt.answer_no ) {
log_error(_("Key generation can only be used in interactive mode\n"));
return;
}
algo = ask_algo( &v4, 0 );
if( !algo ) {
algo = PUBKEY_ALGO_ELGAMAL_E;
both = 1;
tty_printf(_("DSA keypair will have 1024 bits.\n"));
}
nbits = ask_keysize( algo );
expire = ask_expire_interval();
uid = ask_user_id(0);
if( !uid ) {
log_error(_("Key generation cancelled.\n"));
return;
}
dek = ask_passphrase( &s2k );
/* now check whether we are allowed to write to the keyrings */
pub_fname = make_filename(opt.homedir, "pubring.gpg", NULL );
sec_fname = make_filename(opt.homedir, "secring.gpg", NULL );
if( opt.verbose ) {
tty_printf(_("writing public certificate to '%s'\n"), pub_fname );
tty_printf(_("writing secret certificate to '%s'\n"), sec_fname );
}
/* we create the packets as a tree of kbnodes. Because the structure
* we create is known in advance we simply generate a linked list
* The first packet is a dummy comment packet which we flag
* as deleted. The very first packet must always be a KEY packet.
*/
pub_root = make_comment_node("#"); delete_kbnode(pub_root);
sec_root = make_comment_node("#"); delete_kbnode(sec_root);
if( both )
rc = do_create( PUBKEY_ALGO_DSA, 1024, pub_root, sec_root,
dek, s2k, &sk, expire, 1);
else
rc = do_create( algo, nbits, pub_root, sec_root,
dek, s2k, &sk, expire, v4);
if( !rc )
write_uid(pub_root, uid );
if( !rc )
write_uid(sec_root, uid );
if( !rc )
rc = write_selfsig(pub_root, pub_root, sk);
if( !rc )
rc = write_selfsig(sec_root, pub_root, sk);
if( both ) {
rc = do_create( algo, nbits, pub_root, sec_root,
dek, s2k, NULL, expire, 1 );
if( !rc )
rc = write_keybinding(pub_root, pub_root, sk);
if( !rc )
rc = write_keybinding(sec_root, pub_root, sk);
}
if( !rc ) {
KBPOS pub_kbpos;
KBPOS sec_kbpos;
int rc1 = -1;
int rc2 = -1;
/* we can now write the certificates */
if( get_keyblock_handle( pub_fname, 0, &pub_kbpos ) ) {
if( add_keyblock_resource( pub_fname, 1, 0 ) ) {
log_error("can add keyblock file '%s'\n", pub_fname );
rc = G10ERR_CREATE_FILE;
}
else if( get_keyblock_handle( pub_fname, 0, &pub_kbpos ) ) {
log_error("can get keyblock handle for '%s'\n", pub_fname );
rc = G10ERR_CREATE_FILE;
}
}
if( rc )
;
else if( get_keyblock_handle( sec_fname, 1, &sec_kbpos ) ) {
if( add_keyblock_resource( sec_fname, 1, 1 ) ) {
log_error("can add keyblock file '%s'\n", sec_fname );
rc = G10ERR_CREATE_FILE;
}
else if( get_keyblock_handle( sec_fname, 1, &sec_kbpos ) ) {
log_error("can get keyblock handle for '%s'\n", sec_fname );
rc = G10ERR_CREATE_FILE;
}
}
if( rc )
;
else if( (rc=rc1=lock_keyblock( &pub_kbpos )) )
log_error("can't lock public keyring: %s\n", g10_errstr(rc) );
else if( (rc=rc2=lock_keyblock( &sec_kbpos )) )
log_error("can't lock secret keyring: %s\n", g10_errstr(rc) );
else if( (rc=insert_keyblock( &pub_kbpos, pub_root )) )
log_error("can't write public key: %s\n", g10_errstr(rc) );
else if( (rc=insert_keyblock( &sec_kbpos, sec_root )) )
log_error("can't write secret key: %s\n", g10_errstr(rc) );
else {
tty_printf(_("public and secret key created and signed.\n") );
if( algo == PUBKEY_ALGO_DSA )
tty_printf(_("Note that this key cannot be used for "
"encryption. You may want to use\n"
"the command \"--add-key\" to generate a "
"secondary key for this purpose.\n") );
}
if( !rc1 )
unlock_keyblock( &pub_kbpos );
if( !rc2 )
unlock_keyblock( &sec_kbpos );
}
if( rc )
tty_printf(_("Key generation failed: %s\n"), g10_errstr(rc) );
release_kbnode( pub_root );
release_kbnode( sec_root );
if( sk ) /* the unprotected secret key */
free_secret_key(sk);
m_free(uid);
m_free(dek);
m_free(s2k);
m_free(pub_fname);
m_free(sec_fname);
}
/****************
* add a new subkey to an existing key.
* Returns true if a new key has been generated and put into the keyblocks.
*/
int
generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
{
int okay=0, rc=0;
KBNODE node;
PKT_secret_key *sk = NULL; /* this is the primary sk */
int v4, algo;
u32 expire;
unsigned nbits;
char *passphrase = NULL;
DEK *dek = NULL;
STRING2KEY *s2k = NULL;
/* break out the primary secret key */
node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
if( !node ) {
log_error("Oops; secret key not found anymore!\n");
goto leave;
}
/* make a copy of the sk to keep the protected one in the keyblock */
sk = copy_secret_key( NULL, node->pkt->pkt.secret_key );
/* unprotect to get the passphrase */
switch( is_secret_key_protected( sk ) ) {
case -1:
rc = G10ERR_PUBKEY_ALGO;
break;
case 0:
tty_printf("This key is not protected.\n");
break;
default:
tty_printf("Key is protected.\n");
rc = check_secret_key( sk, 0 );
if( !rc )
passphrase = get_last_passphrase();
break;
}
if( rc )
goto leave;
algo = ask_algo( &v4, 1 );
assert(algo);
nbits = ask_keysize( algo );
expire = ask_expire_interval();
if( !cpr_enabled() && !cpr_get_answer_is_yes("keygen.sub.okay",
_("Really create? ") ) )
goto leave;
if( passphrase ) {
s2k = m_alloc_secure( sizeof *s2k );
s2k->mode = opt.s2k_mode;
s2k->hash_algo = opt.s2k_digest_algo;
set_next_passphrase( passphrase );
dek = passphrase_to_dek( NULL, opt.s2k_cipher_algo, s2k, 2 );
}
rc = do_create( algo, nbits, pub_keyblock, sec_keyblock,
dek, s2k, NULL, expire, v4 );
if( !rc )
rc = write_keybinding(pub_keyblock, pub_keyblock, sk);
if( !rc )
rc = write_keybinding(sec_keyblock, pub_keyblock, sk);
if( !rc )
okay = 1;
leave:
if( rc )
log_error(_("Key generation failed: %s\n"), g10_errstr(rc) );
m_free( passphrase );
m_free( dek );
m_free( s2k );
if( sk ) /* release the copy of the (now unprotected) secret key */
free_secret_key(sk);
set_next_passphrase( NULL );
return okay;
}
diff --git a/g10/keyid.c b/g10/keyid.c
index 21e7e12e3..665b3be86 100644
--- a/g10/keyid.c
+++ b/g10/keyid.c
@@ -1,430 +1,430 @@
/* keyid.c - jeyid and fingerprint handling
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <time.h>
#include <assert.h>
#include "util.h"
#include "main.h"
#include "packet.h"
#include "options.h"
#include "mpi.h"
#include "keydb.h"
int
pubkey_letter( int algo )
{
switch( algo ) {
case PUBKEY_ALGO_RSA: return 'R' ;
case PUBKEY_ALGO_RSA_E: return 'r' ;
case PUBKEY_ALGO_RSA_S: return 's' ;
case PUBKEY_ALGO_ELGAMAL_E: return 'g';
case PUBKEY_ALGO_ELGAMAL: return 'G' ;
case PUBKEY_ALGO_DSA: return 'D' ;
default: return '?';
}
}
static MD_HANDLE
do_fingerprint_md( PKT_public_key *pk )
{
MD_HANDLE md;
unsigned n;
unsigned nb[PUBKEY_MAX_NPKEY];
unsigned nn[PUBKEY_MAX_NPKEY];
byte *pp[PUBKEY_MAX_NPKEY];
int i;
int npkey = pubkey_get_npkey( pk->pubkey_algo );
md = md_open( pk->version < 4 ? DIGEST_ALGO_RMD160 : DIGEST_ALGO_SHA1, 0);
n = pk->version < 4 ? 8 : 6;
for(i=0; i < npkey; i++ ) {
nb[i] = mpi_get_nbits(pk->pkey[i]);
pp[i] = mpi_get_buffer( pk->pkey[i], nn+i, NULL );
n += 2 + nn[i];
}
md_putc( md, 0x99 ); /* ctb */
md_putc( md, n >> 8 ); /* 2 byte length header */
md_putc( md, n );
if( pk->version < 4 )
md_putc( md, 3 );
else
md_putc( md, 4 );
{ u32 a = pk->timestamp;
md_putc( md, a >> 24 );
md_putc( md, a >> 16 );
md_putc( md, a >> 8 );
md_putc( md, a );
}
if( pk->version < 4 ) {
u16 a;
if( pk->expiredate )
a = (u16)((pk->expiredate - pk->timestamp) / 86400L);
else
a = 0;
md_putc( md, a >> 8 );
md_putc( md, a );
}
md_putc( md, pk->pubkey_algo );
for(i=0; i < npkey; i++ ) {
md_putc( md, nb[i]>>8);
md_putc( md, nb[i] );
md_write( md, pp[i], nn[i] );
m_free(pp[i]);
}
md_final( md );
return md;
}
static MD_HANDLE
do_fingerprint_md_sk( PKT_secret_key *sk )
{
PKT_public_key pk;
int npkey = pubkey_get_npkey( sk->pubkey_algo ); /* npkey is correct! */
int i;
pk.pubkey_algo = sk->pubkey_algo;
pk.version = sk->version;
pk.timestamp = sk->timestamp;
pk.expiredate = sk->expiredate;
pk.pubkey_algo = sk->pubkey_algo;
for( i=0; i < npkey; i++ )
pk.pkey[i] = sk->skey[i];
return do_fingerprint_md( &pk );
}
/****************
* Get the keyid from the secret key and put it into keyid
* if this is not NULL. Return the 32 low bits of the keyid.
*/
u32
keyid_from_sk( PKT_secret_key *sk, u32 *keyid )
{
u32 lowbits;
u32 dummy_keyid[2];
if( !keyid )
keyid = dummy_keyid;
if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) {
lowbits = pubkey_get_npkey(sk->pubkey_algo) ?
mpi_get_keyid( sk->skey[0], keyid ) : 0; /* take n */
}
else {
const byte *dp;
MD_HANDLE md;
md = do_fingerprint_md_sk(sk);
dp = md_read( md, 0 );
keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
lowbits = keyid[1];
md_close(md);
}
return lowbits;
}
/****************
* Get the keyid from the public key and put it into keyid
* if this is not NULL. Return the 32 low bits of the keyid.
*/
u32
keyid_from_pk( PKT_public_key *pk, u32 *keyid )
{
u32 lowbits;
u32 dummy_keyid[2];
if( !keyid )
keyid = dummy_keyid;
if( pk->keyid[0] || pk->keyid[1] ) {
keyid[0] = pk->keyid[0];
keyid[1] = pk->keyid[1];
lowbits = keyid[1];
}
else if( pk->version < 4 && is_RSA(pk->pubkey_algo) ) {
lowbits = pubkey_get_npkey(pk->pubkey_algo) ?
mpi_get_keyid( pk->pkey[0], keyid ) : 0 ; /* from n */
pk->keyid[0] = keyid[0];
pk->keyid[1] = keyid[1];
}
else {
const byte *dp;
MD_HANDLE md;
md = do_fingerprint_md(pk);
dp = md_read( md, 0 );
keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
lowbits = keyid[1];
md_close(md);
pk->keyid[0] = keyid[0];
pk->keyid[1] = keyid[1];
}
return lowbits;
}
/****************
* Get the keyid from the fingerprint. This function is simple for most
* keys, but has to do a keylookup for old stayle keys.
*/
u32
keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid )
{
u32 dummy_keyid[2];
if( !keyid )
keyid = dummy_keyid;
if( fprint_len != 20 ) {
/* This is special as we have to lookup the key first */
PKT_public_key pk;
int rc;
memset( &pk, 0, sizeof pk );
rc = get_pubkey_byfprint( &pk, fprint, fprint_len );
if( rc ) {
log_error("Oops: keyid_from_fingerprint: no pubkey\n");
keyid[0] = 0;
keyid[1] = 0;
}
else
keyid_from_pk( &pk, keyid );
}
else {
const byte *dp = fprint;
keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
}
return keyid[1];
}
u32
keyid_from_sig( PKT_signature *sig, u32 *keyid )
{
if( keyid ) {
keyid[0] = sig->keyid[0];
keyid[1] = sig->keyid[1];
}
return sig->keyid[1];
}
/****************
* return the number of bits used in the pk
*/
unsigned
nbits_from_pk( PKT_public_key *pk )
{
return pubkey_nbits( pk->pubkey_algo, pk->pkey );
}
/****************
* return the number of bits used in the sk
*/
unsigned
nbits_from_sk( PKT_secret_key *sk )
{
return pubkey_nbits( sk->pubkey_algo, sk->skey );
}
/****************
* return a string with the creation date of the pk
* Note: this is alloced in a static buffer.
* Format is: yyyy-mm-dd
*/
const char *
datestr_from_pk( PKT_public_key *pk )
{
static char buffer[11+5];
struct tm *tp;
time_t atime = pk->timestamp;
tp = gmtime( &atime );
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
return buffer;
}
const char *
datestr_from_sk( PKT_secret_key *sk )
{
static char buffer[11+5];
struct tm *tp;
time_t atime = sk->timestamp;
tp = gmtime( &atime );
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
return buffer;
}
const char *
datestr_from_sig( PKT_signature *sig )
{
static char buffer[11+5];
struct tm *tp;
time_t atime = sig->timestamp;
tp = gmtime( &atime );
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
return buffer;
}
const char *
expirestr_from_pk( PKT_public_key *pk )
{
static char buffer[11+5];
struct tm *tp;
time_t atime;
if( !pk->expiredate )
return "never ";
atime = pk->expiredate;
tp = gmtime( &atime );
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
return buffer;
}
const char *
expirestr_from_sk( PKT_secret_key *sk )
{
static char buffer[11+5];
struct tm *tp;
time_t atime;
if( !sk->expiredate )
return "never ";
atime = sk->expiredate;
tp = gmtime( &atime );
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
return buffer;
}
/**************** .
* Return a byte array with the fingerprint for the given PK/SK
* The length of the array is returned in ret_len. Caller must free
* the array or provide an array of length MAX_FINGERPRINT_LEN.
*/
byte *
fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len )
{
byte *p, *buf;
const char *dp;
size_t len;
unsigned n;
if( pk->version < 4 && is_RSA(pk->pubkey_algo) ) {
/* RSA in version 3 packets is special */
MD_HANDLE md;
md = md_open( DIGEST_ALGO_MD5, 0);
if( pubkey_get_npkey( pk->pubkey_algo ) > 1 ) {
p = buf = mpi_get_buffer( pk->pkey[0], &n, NULL );
md_write( md, p, n );
m_free(buf);
p = buf = mpi_get_buffer( pk->pkey[1], &n, NULL );
md_write( md, p, n );
m_free(buf);
}
md_final(md);
if( !array )
array = m_alloc( 16 );
len = 16;
memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 );
md_close(md);
}
else {
MD_HANDLE md;
md = do_fingerprint_md(pk);
dp = md_read( md, 0 );
len = md_digest_length( md_get_algo( md ) );
assert( len <= MAX_FINGERPRINT_LEN );
if( !array )
array = m_alloc( len );
memcpy(array, dp, len );
md_close(md);
}
*ret_len = len;
return array;
}
byte *
fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len )
{
byte *p, *buf;
const char *dp;
size_t len;
unsigned n;
if( sk->version < 4 && is_RSA(sk->pubkey_algo) ) {
/* RSA in version 3 packets is special */
MD_HANDLE md;
md = md_open( DIGEST_ALGO_MD5, 0);
if( pubkey_get_npkey( sk->pubkey_algo ) > 1 ) {
p = buf = mpi_get_buffer( sk->skey[1], &n, NULL );
md_write( md, p, n );
m_free(buf);
p = buf = mpi_get_buffer( sk->skey[0], &n, NULL );
md_write( md, p, n );
m_free(buf);
}
md_final(md);
if( !array )
array = m_alloc( 16 );
len = 16;
memcpy(array, md_read(md, DIGEST_ALGO_MD5), 16 );
md_close(md);
}
else {
MD_HANDLE md;
md = do_fingerprint_md_sk(sk);
dp = md_read( md, 0 );
len = md_digest_length( md_get_algo( md ) );
assert( len <= MAX_FINGERPRINT_LEN );
if( !array )
array = m_alloc( len );
memcpy(array, dp, len );
md_close(md);
}
*ret_len = len;
return array;
}
diff --git a/g10/keylist.c b/g10/keylist.c
index f2ded0455..3c68680e4 100644
--- a/g10/keylist.c
+++ b/g10/keylist.c
@@ -1,421 +1,421 @@
/* keylist.c
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "options.h"
#include "packet.h"
#include "errors.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "trustdb.h"
#include "main.h"
#include "i18n.h"
static void list_all(int);
static void list_one(const char *name, int secret);
static void list_keyblock( KBNODE keyblock, int secret );
static void fingerprint( PKT_public_key *pk, PKT_secret_key *sk );
/****************
* List the keys
* If NNAMES is 0; all available keys are listed
*/
void
public_key_list( int nnames, char **names )
{
if( !nnames )
list_all(0);
else { /* List by user id */
for( ; nnames ; nnames--, names++ )
list_one( *names, 0 );
}
}
void
secret_key_list( int nnames, char **names )
{
if( !nnames )
list_all(1);
else { /* List by user id */
for( ; nnames ; nnames--, names++ )
list_one( *names, 1 );
}
}
static void
list_all( int secret )
{
KBPOS kbpos;
KBNODE keyblock = NULL;
int rc=0;
int lastresno;
rc = enum_keyblocks( secret? 5:0, &kbpos, &keyblock );
if( rc ) {
if( rc != -1 )
log_error("enum_keyblocks(open) failed: %s\n", g10_errstr(rc) );
goto leave;
}
lastresno = -1;
while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) {
if( lastresno != kbpos.resno ) {
const char *s = keyblock_resource_name( &kbpos );
int i;
lastresno = kbpos.resno;
printf("%s\n", s );
for(i=strlen(s); i; i-- )
putchar('-');
putchar('\n');
}
merge_keys_and_selfsig( keyblock );
list_keyblock( keyblock, secret );
release_kbnode( keyblock ); keyblock = NULL;
}
if( rc && rc != -1 )
log_error("enum_keyblocks(read) failed: %s\n", g10_errstr(rc));
leave:
enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
release_kbnode( keyblock );
}
static void
list_one( const char *name, int secret )
{
int rc = 0;
KBNODE keyblock = NULL;
if( secret ) {
KBPOS kbpos;
rc = secret? find_secret_keyblock_byname( &kbpos, name )
: find_keyblock_byname( &kbpos, name );
if( rc ) {
log_error("%s: user not found\n", name );
return;
}
rc = read_keyblock( &kbpos, &keyblock );
if( rc ) {
log_error("%s: keyblock read problem: %s\n", name, g10_errstr(rc) );
return;
}
merge_keys_and_selfsig( keyblock );
list_keyblock( keyblock, secret );
release_kbnode( keyblock );
}
else {
GETKEY_CTX ctx;
rc = get_pubkey_byname( &ctx, NULL, name, &keyblock );
if( rc ) {
log_error("%s: %s\n", name, g10_errstr(rc) );
get_pubkey_end( ctx );
return;
}
do {
list_keyblock( keyblock, 0 );
release_kbnode( keyblock );
} while( !get_pubkey_next( ctx, NULL, &keyblock ) );
get_pubkey_end( ctx );
}
}
static void
list_keyblock( KBNODE keyblock, int secret )
{
int rc = 0;
KBNODE kbctx;
KBNODE node;
PKT_public_key *pk;
PKT_secret_key *sk;
u32 keyid[2];
int any=0;
int trustletter = 0;
/* get the keyid from the keyblock */
node = find_kbnode( keyblock, secret? PKT_SECRET_KEY : PKT_PUBLIC_KEY );
if( !node ) {
log_error("Oops; key lost!\n");
return;
}
if( secret ) {
pk = NULL;
sk = node->pkt->pkt.secret_key;
keyid_from_sk( sk, keyid );
if( opt.with_colons )
printf("sec::%u:%d:%08lX%08lX:%s:%s:::",
nbits_from_sk( sk ),
sk->pubkey_algo,
(ulong)keyid[0],(ulong)keyid[1],
datestr_from_sk( sk ),
sk->expiredate? strtimestamp(sk->expiredate):""
/* fixme: add LID here */ );
else
printf("sec %4u%c/%08lX %s ", nbits_from_sk( sk ),
pubkey_letter( sk->pubkey_algo ),
(ulong)keyid[1],
datestr_from_sk( sk ) );
}
else {
pk = node->pkt->pkt.public_key;
sk = NULL;
keyid_from_pk( pk, keyid );
if( opt.with_colons ) {
trustletter = query_trust_info( pk );
printf("pub:%c:%u:%d:%08lX%08lX:%s:%s:",
trustletter,
nbits_from_pk( pk ),
pk->pubkey_algo,
(ulong)keyid[0],(ulong)keyid[1],
datestr_from_pk( pk ),
pk->expiredate? strtimestamp(pk->expiredate):""
);
if( pk->local_id )
printf("%lu", pk->local_id );
putchar(':');
if( pk->local_id )
putchar( get_ownertrust_info( pk->local_id ) );
putchar(':');
}
else
printf("pub %4u%c/%08lX %s ", nbits_from_pk( pk ),
pubkey_letter( pk->pubkey_algo ),
(ulong)keyid[1],
datestr_from_pk( pk ) );
}
for( kbctx=NULL; (node=walk_kbnode( keyblock, &kbctx, 0)) ; ) {
if( node->pkt->pkttype == PKT_USER_ID ) {
if( any ) {
if( opt.with_colons )
printf("uid:::::::::");
else
printf("uid%*s", 28, "");
}
print_string( stdout, node->pkt->pkt.user_id->name,
node->pkt->pkt.user_id->len, opt.with_colons );
if( opt.with_colons )
putchar(':');
putchar('\n');
if( !any ) {
if( opt.fingerprint )
fingerprint( pk, sk );
any = 1;
}
}
else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
u32 keyid2[2];
PKT_public_key *pk2 = node->pkt->pkt.public_key;
if( !any ) {
putchar('\n');
if( opt.fingerprint )
fingerprint( pk, sk ); /* of the main key */
any = 1;
}
keyid_from_pk( pk2, keyid2 );
if( opt.with_colons ) {
printf("sub:%c:%u:%d:%08lX%08lX:%s:%s:",
trustletter,
nbits_from_pk( pk2 ),
pk2->pubkey_algo,
(ulong)keyid2[0],(ulong)keyid2[1],
datestr_from_pk( pk2 ),
pk2->expiredate? strtimestamp(pk2->expiredate):""
/* fixme: add LID and ownertrust here */
);
if( pk->local_id ) /* use the local_id of the main key??? */
printf("%lu", pk->local_id );
putchar(':');
putchar(':');
putchar('\n');
}
else
printf("sub %4u%c/%08lX %s\n", nbits_from_pk( pk2 ),
pubkey_letter( pk2->pubkey_algo ),
(ulong)keyid2[1],
datestr_from_pk( pk2 ) );
if( opt.fingerprint > 1 )
fingerprint( pk2, NULL );
}
else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
u32 keyid2[2];
PKT_secret_key *sk2 = node->pkt->pkt.secret_key;
if( !any ) {
putchar('\n');
if( opt.fingerprint )
fingerprint( pk, sk ); /* of the main key */
any = 1;
}
keyid_from_sk( sk2, keyid2 );
if( opt.with_colons )
printf("ssb::%u:%d:%08lX%08lX:%s:%s:::\n",
nbits_from_sk( sk2 ),
sk2->pubkey_algo,
(ulong)keyid2[0],(ulong)keyid2[1],
datestr_from_sk( sk2 ),
sk2->expiredate? strtimestamp(sk2->expiredate):""
/* fixme: add LID */
);
else
printf("ssb %4u%c/%08lX %s\n", nbits_from_sk( sk2 ),
pubkey_letter( sk2->pubkey_algo ),
(ulong)keyid2[1],
datestr_from_sk( sk2 ) );
if( opt.fingerprint > 1 )
fingerprint( NULL, sk2 );
}
else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) {
PKT_signature *sig = node->pkt->pkt.signature;
int sigrc;
if( !any ) { /* no user id, (maybe a revocation follows)*/
if( sig->sig_class == 0x20 )
puts("[revoked]");
else if( sig->sig_class == 0x18 )
puts("[key binding]");
else
putchar('\n');
if( opt.fingerprint )
fingerprint( pk, sk );
any=1;
}
if( sig->sig_class == 0x20 || sig->sig_class == 0x30 )
fputs("rev", stdout);
else if( (sig->sig_class&~3) == 0x10 )
fputs("sig", stdout);
else if( sig->sig_class == 0x18 )
fputs("sig", stdout);
else {
if( opt.with_colons )
printf("sig::::::::::%02x:\n",sig->sig_class );
else
printf("sig "
"[unexpected signature class 0x%02x]\n",sig->sig_class );
continue;
}
if( opt.check_sigs ) {
fflush(stdout);
rc = check_key_signature( keyblock, node, NULL );
switch( rc ) {
case 0: sigrc = '!'; break;
case G10ERR_BAD_SIGN: sigrc = '-'; break;
case G10ERR_NO_PUBKEY: sigrc = '?'; break;
default: sigrc = '%'; break;
}
}
else {
rc = 0;
sigrc = ' ';
}
if( opt.with_colons ) {
putchar(':');
if( sigrc != ' ' )
putchar(sigrc);
printf(":::%08lX%08lX:%s::::", (ulong)sig->keyid[0],
(ulong)sig->keyid[1], datestr_from_sig(sig));
}
else
printf("%c %08lX %s ",
sigrc, (ulong)sig->keyid[1], datestr_from_sig(sig));
if( sigrc == '%' )
printf("[%s] ", g10_errstr(rc) );
else if( sigrc == '?' )
;
else {
size_t n;
char *p = get_user_id( sig->keyid, &n );
print_string( stdout, p, n, opt.with_colons );
m_free(p);
}
if( opt.with_colons )
printf(":%02x:", sig->sig_class );
putchar('\n');
/* FIXME: check or list other sigs here (subpkt PRIV_ADD_SIG)*/
}
}
if( !any ) {/* oops, no user id */
if( opt.with_colons )
putchar(':');
putchar('\n');
}
}
static void
fingerprint( PKT_public_key *pk, PKT_secret_key *sk )
{
byte *array, *p;
size_t i, n;
p = array = pk? fingerprint_from_pk( pk, NULL, &n )
: fingerprint_from_sk( sk, NULL, &n );
if( opt.with_colons ) {
printf("fpr:::::::::");
for(i=0; i < n ; i++, p++ )
printf("%02X", *p );
putchar(':');
}
else {
printf(" Key fingerprint =");
if( n == 20 ) {
for(i=0; i < n ; i++, i++, p += 2 ) {
if( i == 10 )
putchar(' ');
printf(" %02X%02X", *p, p[1] );
}
}
else {
for(i=0; i < n ; i++, p++ ) {
if( i && !(i%8) )
putchar(' ');
printf(" %02X", *p );
}
}
}
putchar('\n');
m_free(array);
}
diff --git a/g10/ks-proto.c b/g10/ks-proto.c
index b5109f2ad..43abf468a 100644
--- a/g10/ks-proto.c
+++ b/g10/ks-proto.c
@@ -1,155 +1,155 @@
/* ks-proto.c keyserver protocol handling
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 extended HKP protocol:
*
* GET /pks/lookup[/<gnupg_user_id>][?[op=<cmd>][&armor=0][&search=<keywords>]]
*
* Default is: "armor=1", "op=get". "search" is only allowed if gnupg_user_id
* is not present. GET maybe replaced by HEAD in which case only some status
* information is returned.
*
* Hmmm, I don't like it, the better solution is to use:
*
* /pks/gnupg/get for binary lookups
* /pks/gnupg/upd to update a key
* /pks/gnupg/ins to insert a new key
*
* Optional a version string can be inserted as in:
*
* /pks/gnupg/v1.0/get
*
* Returned HTTP options:
* X-Key-Hash: <rmd160 hash value of the keyblock>
* X-Key-MTime: <last modification time>
* X-Key-LID: <local_key_id_used_for_update_etc>
* [fixme: is X-.... allowed?]
*
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include "util.h"
#include "ks-proto.h"
static int
do_read( int fd, char *buffer, size_t bufsize, int *ret_nread )
{
int n;
fd_set rfds;
struct timeval tv;
int rc;
*ret_nread = 0;
do {
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
tv.tv_sec = 1;
tv.tv_usec = 0;
if( !(rc=select(fd+1, &rfds, NULL, NULL, &tv)) )
return 0; /* timeout */
if( rc == -1 ) {
log_error("select() error: %s\n", strerror(errno));
return -1;
}
do {
n = read(fd, buffer, bufsize );
if( n >= 0 && n > bufsize )
log_bug("bogus read from fd %d (n=%d)\n", fd, n );
} while( n == -1 && errno == EINTR );
if( n == -1 ) {
log_error("read error on fd %d: %s\n", fd, strerror(errno) );
return -1;
}
} while( !n );
*ret_nread = n;
return 0;
}
int
ks_get_request( int fd, KS_TRANS *req )
{
char *p, *p2, buf[500];
int nread, n;
int state = 0;
req->err = 0;
req->data = NULL;
while( !do_read( fd, buf, DIM(buf)-1, &nread ) {
p = buf;
if( !state ) {
/* replace the trailing LF with a 0 */
for(p2=p,n=0; n < nread && *p2 != '\n'; p2++ )
;
if( *p2 != '\n' ) {
req->err = KS_ERR_REQ_TOO_LONG;
break;
}
*p2++ = 0;
n++;
/* now look at the request. Note that the isspace() will work
* because there is still a CR before the 0 */
if( (p[0] == 'G' || p[0] == 'g')
&& (p[1] == 'E' || p[1] == 'e')
&& (p[2] == 'T' || p[2] == 't') && isspace( p[3] ) ) {
req->cmd = KS_REQ_GET;
p += 4;
}
else if( (p[0] == 'H' || p[0] == 'h')
&& (p[1] == 'E' || p[1] == 'e')
&& (p[2] == 'A' || p[2] == 'a')
&& (p[3] == 'D' || p[3] == 'd') && isspace( p[4] ) ) {
req->cmd = KS_REQ_HEAD;
p += 5;
}
else if( (p[0] == 'H' || p[0] == 'h')
&& (p[1] == 'E' || p[1] == 'e')
&& (p[2] == 'L' || p[2] == 'l')
&& (p[3] == 'P' || p[3] == 'p') && isspace( p[4] ) ) {
req->cmd = KS_REQ_HELP;
p += 5;
}
else
req->cmd = KS_REQ_UNKNOWN;
/* skip spaces, store args and remaining data */
while( *p == ' ' || *p == '\t' )
p++;
/* fixme: remove trailing blanks from args */
req->args = p;
p = p2; /* p now points to the remaining n bytes in the buffer */
state = 1;
}
if( state == 1 ) {
/* read the option lines */
}
}
}
diff --git a/g10/ks-proto.h b/g10/ks-proto.h
index 67d2ed4ae..bd58db5f9 100644
--- a/g10/ks-proto.h
+++ b/g10/ks-proto.h
@@ -1,23 +1,23 @@
/* ks-proto.h
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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_KS_PROTO_H
#define G10_KS_PROTO_H
#endif /*G10_KS_PROTO_H*/
diff --git a/g10/main.h b/g10/main.h
index 72f433fcc..b917bae26 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -1,143 +1,143 @@
/* main.h
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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_MAIN_H
#define G10_MAIN_H
#include "types.h"
#include "iobuf.h"
#include "mpi.h"
#include "cipher.h"
#include "keydb.h"
#define DEFAULT_CIPHER_ALGO CIPHER_ALGO_BLOWFISH
#define DEFAULT_PUBKEY_ALGO PUBKEY_ALGO_ELGAMAL
#define DEFAULT_DIGEST_ALGO DIGEST_ALGO_RMD160
typedef struct {
int header_okay;
PK_LIST pk_list;
cipher_filter_context_t cfx;
} encrypt_filter_context_t;
/*-- g10.c --*/
extern int g10_errors_seen;
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
void g10_exit(int rc) __attribute__ ((noreturn));
#else
void g10_exit(int rc);
#endif
void print_pubkey_algo_note( int algo );
void print_cipher_algo_note( int algo );
void print_digest_algo_note( int algo );
/*-- misc.c --*/
void trap_unaligned(void);
void disable_core_dumps(void);
u16 checksum_u16( unsigned n );
u16 checksum( byte *p, unsigned n );
u16 checksum_mpi( MPI a );
u16 checksum_mpi_counted_nbits( MPI a );
u32 buffer_to_u32( const byte *buffer );
/*-- helptext.c --*/
void display_online_help( const char *keyword );
/*-- encode.c --*/
int encode_symmetric( const char *filename );
int encode_store( const char *filename );
int encode_crypt( const char *filename, STRLIST remusr );
int encrypt_filter( void *opaque, int control,
IOBUF a, byte *buf, size_t *ret_len);
/*-- sign.c --*/
int complete_sig( PKT_signature *sig, PKT_secret_key *sk, MD_HANDLE md );
int sign_file( STRLIST filenames, int detached, STRLIST locusr,
int encrypt, STRLIST remusr, const char *outfile );
int clearsign_file( const char *fname, STRLIST locusr, const char *outfile );
/*-- sig-check.c --*/
int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig );
/*-- delkey.c --*/
int delete_key( const char *username, int secure );
/*-- keyedit.c --*/
void keyedit_menu( const char *username, STRLIST locusr, STRLIST cmds );
/*-- keygen.c --*/
u32 ask_expiredate(void);
void generate_keypair(void);
int keygen_add_key_expire( PKT_signature *sig, void *opaque );
int keygen_add_std_prefs( PKT_signature *sig, void *opaque );
int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock );
/*-- openfile.c --*/
int overwrite_filep( const char *fname );
int open_outfile( const char *iname, int mode, IOBUF *a );
IOBUF open_sigfile( const char *iname );
void copy_options_file( const char *destdir );
/*-- seskey.c --*/
void make_session_key( DEK *dek );
MPI encode_session_key( DEK *dek, unsigned nbits );
MPI encode_md_value( int pubkey_algo, MD_HANDLE md,
int hash_algo, unsigned nbits );
/*-- comment.c --*/
KBNODE make_comment_node( const char *s );
KBNODE make_mpi_comment_node( const char *s, MPI a );
/*-- import.c --*/
int import_keys( const char *filename, int fast );
/*-- export.c --*/
int export_pubkeys( STRLIST users, int onlyrfc );
int export_seckeys( STRLIST users );
/* dearmor.c --*/
int dearmor_file( const char *fname );
int enarmor_file( const char *fname );
/*-- revoke.c --*/
int gen_revoke( const char *uname );
/*-- keylist.c --*/
void public_key_list( int nnames, char **names );
void secret_key_list( int nnames, char **names );
/*-- verify.c --*/
int verify_signatures( int nfiles, char **files );
/*-- decrypt.c --*/
int decrypt_message( const char *filename );
/*-- plaintext.c --*/
int hash_datafiles( MD_HANDLE md, STRLIST files, const char *sigfilename,
int textmode );
/*-- signal.c --*/
void init_signals(void);
void pause_on_sigusr( int which );
void block_all_signals(void);
void unblock_all_signals(void);
#endif /*G10_MAIN_H*/
diff --git a/g10/mainproc.c b/g10/mainproc.c
index acf5bf5e7..0d5c88f5c 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -1,944 +1,944 @@
/* mainproc.c - handle packets
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <time.h>
#include "packet.h"
#include "iobuf.h"
#include "memory.h"
#include "options.h"
#include "util.h"
#include "cipher.h"
#include "keydb.h"
#include "filter.h"
#include "cipher.h"
#include "main.h"
#include "status.h"
#include "i18n.h"
#include "trustdb.h"
/****************
* Structure to hold the context
*/
typedef struct {
PKT_public_key *last_pubkey;
PKT_secret_key *last_seckey;
PKT_user_id *last_user_id;
md_filter_context_t mfx;
int sigs_only; /* process only signatures and reject all other stuff */
int encrypt_only; /* process only encrytion messages */
STRLIST signed_data;
const char *sigfilename;
DEK *dek;
int last_was_session_key;
KBNODE list; /* the current list of packets */
int have_data;
IOBUF iobuf; /* used to get the filename etc. */
int trustletter; /* temp usage in list_node */
ulong local_id; /* ditto */
} *CTX;
static int do_proc_packets( CTX c, IOBUF a );
static void list_node( CTX c, KBNODE node );
static void proc_tree( CTX c, KBNODE node );
static void
release_list( CTX c )
{
if( !c->list )
return;
proc_tree(c, c->list );
release_kbnode( c->list );
c->list = NULL;
}
static int
add_onepass_sig( CTX c, PACKET *pkt )
{
KBNODE node;
if( c->list ) { /* add another packet */
if( c->list->pkt->pkttype != PKT_ONEPASS_SIG ) {
log_error("add_onepass_sig: another packet is in the way\n");
release_list( c );
c->list = new_kbnode( pkt );
}
else
add_kbnode( c->list, new_kbnode( pkt ));
}
else /* insert the first one */
c->list = node = new_kbnode( pkt );
return 1;
}
static int
add_user_id( CTX c, PACKET *pkt )
{
if( !c->list ) {
log_error("orphaned user id\n" );
return 0;
}
add_kbnode( c->list, new_kbnode( pkt ) );
return 1;
}
static int
add_subkey( CTX c, PACKET *pkt )
{
if( !c->list ) {
log_error("subkey w/o mainkey\n" );
return 0;
}
add_kbnode( c->list, new_kbnode( pkt ) );
return 1;
}
static int
add_signature( CTX c, PACKET *pkt )
{
KBNODE node;
if( pkt->pkttype == PKT_SIGNATURE && !c->list ) {
/* This is the first signature for the following datafile.
* G10 does not write such packets; instead it always uses
* onepass-sig packets. The drawback of PGP's method
* of prepending the signature to the data is
* that it is not possible to make a signature from data read
* from stdin. (G10 is able to read PGP stuff anyway.) */
node = new_kbnode( pkt );
c->list = node;
return 1;
}
else if( !c->list )
return 0; /* oops (invalid packet sequence)*/
else if( !c->list->pkt )
BUG(); /* so nicht */
/* add a new signature node id at the end */
node = new_kbnode( pkt );
add_kbnode( c->list, node );
return 1;
}
static void
proc_symkey_enc( CTX c, PACKET *pkt )
{
PKT_symkey_enc *enc;
enc = pkt->pkt.symkey_enc;
if( enc->seskeylen )
log_error( "symkey_enc packet with session keys are not supported!\n");
else {
c->last_was_session_key = 2;
c->dek = passphrase_to_dek( NULL, enc->cipher_algo, &enc->s2k, 0 );
}
free_packet(pkt);
}
static void
proc_pubkey_enc( CTX c, PACKET *pkt )
{
PKT_pubkey_enc *enc;
int result = 0;
/* check whether the secret key is available and store in this case */
c->last_was_session_key = 1;
enc = pkt->pkt.pubkey_enc;
/*printf("enc: encrypted by a pubkey with keyid %08lX\n", enc->keyid[1] );*/
if( is_ELGAMAL(enc->pubkey_algo)
|| enc->pubkey_algo == PUBKEY_ALGO_DSA
|| is_RSA(enc->pubkey_algo) ) {
if ( !c->dek ) {
c->dek = m_alloc_secure( sizeof *c->dek );
if( (result = get_session_key( enc, c->dek )) ) {
/* error: delete the DEK */
m_free(c->dek); c->dek = NULL;
}
}
}
else
result = G10ERR_PUBKEY_ALGO;
if( result == -1 )
;
else if( !result ) {
if( opt.verbose > 1 )
log_info( _("public key encrypted data: Good DEK\n") );
}
else {
log_error(_("public key decryption failed: %s\n"), g10_errstr(result));
}
free_packet(pkt);
}
static void
proc_encrypted( CTX c, PACKET *pkt )
{
int result = 0;
/*printf("dat: %sencrypted data\n", c->dek?"":"conventional ");*/
if( !c->dek && !c->last_was_session_key ) {
/* assume this is old conventional encrypted data */
c->dek = passphrase_to_dek( NULL,
opt.def_cipher_algo ? opt.def_cipher_algo
: DEFAULT_CIPHER_ALGO, NULL, 0 );
}
else if( !c->dek )
result = G10ERR_NO_SECKEY;
if( !result )
result = decrypt_data( pkt->pkt.encrypted, c->dek );
m_free(c->dek); c->dek = NULL;
if( result == -1 )
;
else if( !result ) {
if( opt.verbose > 1 )
log_info(_("decryption okay\n"));
}
else {
log_error(_("decryption failed: %s\n"), g10_errstr(result));
/* FIXME: if this is secret key not available, try with
* other keys */
}
free_packet(pkt);
c->last_was_session_key = 0;
}
static void
proc_plaintext( CTX c, PACKET *pkt )
{
PKT_plaintext *pt = pkt->pkt.plaintext;
int any, clearsig, rc;
KBNODE n;
if( pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8 ) )
log_info(_("NOTE: sender requested \"for-your-eyes-only\"\n"));
else if( opt.verbose )
log_info(_("original file name='%.*s'\n"), pt->namelen, pt->name);
free_md_filter_context( &c->mfx );
c->mfx.md = md_open( 0, 0);
/* fixme: we may need to push the textfilter if we have sigclass 1
* and no armoring - Not yet tested */
any = clearsig = 0;
for(n=c->list; n; n = n->next ) {
if( n->pkt->pkttype == PKT_ONEPASS_SIG ) {
if( n->pkt->pkt.onepass_sig->digest_algo ) {
md_enable( c->mfx.md, n->pkt->pkt.onepass_sig->digest_algo );
any = 1;
}
/* Check whether this is a cleartext signature. We assume that
* we have one if the sig_class is 1 and the keyid is 0, that
* are the faked packets produced by armor.c. There is a
* possibility that this fails, but there is no other easy way
* to do it. (We could use a special packet type to indicate
* this, but this may also be faked - it simply can't be verified
* and is _no_ security issue)
*/
if( n->pkt->pkt.onepass_sig->sig_class == 0x01
&& !n->pkt->pkt.onepass_sig->keyid[0]
&& !n->pkt->pkt.onepass_sig->keyid[1] )
clearsig = 1;
}
}
if( !any ) { /* no onepass sig packet: enable all standard algos */
md_enable( c->mfx.md, DIGEST_ALGO_RMD160 );
md_enable( c->mfx.md, DIGEST_ALGO_SHA1 );
md_enable( c->mfx.md, DIGEST_ALGO_MD5 );
}
md_start_debug( c->mfx.md, "verify" );
rc = handle_plaintext( pt, &c->mfx, c->sigs_only, clearsig );
if( rc == G10ERR_CREATE_FILE && !c->sigs_only) {
/* can't write output but we hash it anyway to
* check the signature */
rc = handle_plaintext( pt, &c->mfx, 1, clearsig );
}
if( rc )
log_error( "handle plaintext failed: %s\n", g10_errstr(rc));
free_packet(pkt);
c->last_was_session_key = 0;
}
static int
proc_compressed_cb( IOBUF a, void *info )
{
return proc_signature_packets( a, ((CTX)info)->signed_data,
((CTX)info)->sigfilename );
}
static int
proc_encrypt_cb( IOBUF a, void *info )
{
return proc_encryption_packets( a );
}
static void
proc_compressed( CTX c, PACKET *pkt )
{
PKT_compressed *zd = pkt->pkt.compressed;
int rc;
/*printf("zip: compressed data packet\n");*/
if( c->sigs_only )
rc = handle_compressed( zd, proc_compressed_cb, c );
else if( c->encrypt_only )
rc = handle_compressed( zd, proc_encrypt_cb, c );
else
rc = handle_compressed( zd, NULL, NULL );
if( rc )
log_error("uncompressing failed: %s\n", g10_errstr(rc));
free_packet(pkt);
c->last_was_session_key = 0;
}
/****************
* check the signature
* Returns: 0 = valid signature or an error code
*/
static int
do_check_sig( CTX c, KBNODE node, int *is_selfsig )
{
PKT_signature *sig;
MD_HANDLE md;
int algo, rc;
assert( node->pkt->pkttype == PKT_SIGNATURE );
if( is_selfsig )
*is_selfsig = 0;
sig = node->pkt->pkt.signature;
algo = sig->digest_algo;
if( !algo )
return G10ERR_PUBKEY_ALGO;
if( (rc=check_digest_algo(algo)) )
return rc;
if( c->mfx.md ) {
m_check(c->mfx.md);
if( c->mfx.md->list )
m_check( c->mfx.md->list );
}
if( sig->sig_class == 0x00 ) {
if( c->mfx.md )
md = md_copy( c->mfx.md );
else /* detached signature */
md = md_open( 0, 0 ); /* signature_check() will enable the md*/
}
else if( sig->sig_class == 0x01 ) {
/* how do we know that we have to hash the (already hashed) text
* in canonical mode ??? (calculating both modes???) */
if( c->mfx.md )
md = md_copy( c->mfx.md );
else /* detached signature */
md = md_open( 0, 0 ); /* signature_check() will enable the md*/
}
else if( (sig->sig_class&~3) == 0x10
|| sig->sig_class == 0x18
|| sig->sig_class == 0x20
|| sig->sig_class == 0x30 ) { /* classes 0x10..0x17,0x20,0x30 */
if( c->list->pkt->pkttype == PKT_PUBLIC_KEY
|| c->list->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
return check_key_signature( c->list, node, is_selfsig );
}
else {
log_error("invalid root packet for sigclass %02x\n",
sig->sig_class);
return G10ERR_SIG_CLASS;
}
}
else
return G10ERR_SIG_CLASS;
rc = signature_check( sig, md );
md_close(md);
return rc;
}
static void
print_userid( PACKET *pkt )
{
if( !pkt )
BUG();
if( pkt->pkttype != PKT_USER_ID ) {
printf("ERROR: unexpected packet type %d", pkt->pkttype );
return;
}
print_string( stdout, pkt->pkt.user_id->name, pkt->pkt.user_id->len,
opt.with_colons );
}
static void
print_fingerprint( PKT_public_key *pk, PKT_secret_key *sk )
{
byte array[MAX_FINGERPRINT_LEN], *p;
size_t i, n;
if( sk )
fingerprint_from_sk( sk, array, &n );
else
fingerprint_from_pk( pk, array, &n );
p = array;
if( opt.with_colons ) {
printf("fpr:::::::::");
for(i=0; i < n ; i++, p++ )
printf("%02X", *p );
putchar(':');
}
else {
printf(" Key fingerprint =");
if( n == 20 ) {
for(i=0; i < n ; i++, i++, p += 2 ) {
if( i == 10 )
putchar(' ');
printf(" %02X%02X", *p, p[1] );
}
}
else {
for(i=0; i < n ; i++, p++ ) {
if( i && !(i%8) )
putchar(' ');
printf(" %02X", *p );
}
}
}
putchar('\n');
}
/****************
* List the certificate in a user friendly way
*/
static void
list_node( CTX c, KBNODE node )
{
int any=0;
int mainkey;
if( !node )
;
else if( (mainkey = (node->pkt->pkttype == PKT_PUBLIC_KEY) )
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
PKT_public_key *pk = node->pkt->pkt.public_key;
if( opt.with_colons ) {
u32 keyid[2];
keyid_from_pk( pk, keyid );
if( mainkey ) {
c->local_id = pk->local_id;
c->trustletter = query_trust_info( pk );
}
printf("%s:%c:%u:%d:%08lX%08lX:%s:%s:",
mainkey? "pub":"sub",
c->trustletter,
nbits_from_pk( pk ),
pk->pubkey_algo,
(ulong)keyid[0],(ulong)keyid[1],
datestr_from_pk( pk ),
pk->expiredate? strtimestamp(pk->expiredate):"" );
if( c->local_id )
printf("%lu", c->local_id );
putchar(':');
if( c->local_id )
putchar( get_ownertrust_info( c->local_id ) );
putchar(':');
}
else
printf("%s %4u%c/%08lX %s ",
mainkey? "pub":"sub",
nbits_from_pk( pk ),
pubkey_letter( pk->pubkey_algo ),
(ulong)keyid_from_pk( pk, NULL ),
datestr_from_pk( pk ) );
if( mainkey ) {
/* and now list all userids with their signatures */
for( node = node->next; node; node = node->next ) {
if( node->pkt->pkttype == PKT_SIGNATURE ) {
if( !any ) {
if( node->pkt->pkt.signature->sig_class == 0x20 )
puts("[revoked]");
else
putchar('\n');
any = 1;
}
list_node(c, node );
}
else if( node->pkt->pkttype == PKT_USER_ID ) {
if( any ) {
if( opt.with_colons )
printf("uid:::::::::");
else
printf( "uid%*s", 28, "" );
}
print_userid( node->pkt );
if( opt.with_colons )
putchar(':');
putchar('\n');
if( opt.fingerprint && !any )
print_fingerprint( pk, NULL );
any=1;
}
else if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
if( !any ) {
putchar('\n');
any = 1;
}
list_node(c, node );
}
}
}
if( !any )
putchar('\n');
if( !mainkey && opt.fingerprint > 1 )
print_fingerprint( pk, NULL );
}
else if( (mainkey = (node->pkt->pkttype == PKT_SECRET_KEY) )
|| node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
PKT_secret_key *sk = node->pkt->pkt.secret_key;
if( opt.with_colons ) {
u32 keyid[2];
keyid_from_sk( sk, keyid );
printf("%s::%u:%d:%08lX%08lX:%s:%s:::",
mainkey? "sec":"ssb",
nbits_from_sk( sk ),
sk->pubkey_algo,
(ulong)keyid[0],(ulong)keyid[1],
datestr_from_sk( sk ),
sk->expiredate? strtimestamp(sk->expiredate):""
/* fixme: add LID */ );
}
else
printf("%s %4u%c/%08lX %s ",
mainkey? "sec":"ssb",
nbits_from_sk( sk ),
pubkey_letter( sk->pubkey_algo ),
(ulong)keyid_from_sk( sk, NULL ),
datestr_from_sk( sk ) );
if( mainkey ) {
/* and now list all userids with their signatures */
for( node = node->next; node; node = node->next ) {
if( node->pkt->pkttype == PKT_SIGNATURE ) {
if( !any ) {
if( node->pkt->pkt.signature->sig_class == 0x20 )
puts("[revoked]");
else
putchar('\n');
any = 1;
}
list_node(c, node );
}
else if( node->pkt->pkttype == PKT_USER_ID ) {
if( any ) {
if( opt.with_colons )
printf("uid:::::::::");
else
printf( "uid%*s", 28, "" );
}
print_userid( node->pkt );
if( opt.with_colons )
putchar(':');
putchar('\n');
if( opt.fingerprint && !any )
print_fingerprint( NULL, sk );
any=1;
}
else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
if( !any ) {
putchar('\n');
any = 1;
}
list_node(c, node );
}
}
}
if( !any )
putchar('\n');
if( !mainkey && opt.fingerprint > 1 )
print_fingerprint( NULL, sk );
}
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
PKT_signature *sig = node->pkt->pkt.signature;
int is_selfsig = 0;
int rc2=0;
size_t n;
char *p;
int sigrc = ' ';
if( !opt.list_sigs )
return;
if( sig->sig_class == 0x20 || sig->sig_class == 0x30 )
fputs("rev", stdout);
else
fputs("sig", stdout);
if( opt.check_sigs ) {
fflush(stdout);
switch( (rc2=do_check_sig( c, node, &is_selfsig )) ) {
case 0: sigrc = '!'; break;
case G10ERR_BAD_SIGN: sigrc = '-'; break;
case G10ERR_NO_PUBKEY: sigrc = '?'; break;
default: sigrc = '%'; break;
}
}
else { /* check whether this is a self signature */
u32 keyid[2];
if( c->list->pkt->pkttype == PKT_PUBLIC_KEY
|| c->list->pkt->pkttype == PKT_SECRET_KEY ) {
if( c->list->pkt->pkttype == PKT_PUBLIC_KEY )
keyid_from_pk( c->list->pkt->pkt.public_key, keyid );
else
keyid_from_sk( c->list->pkt->pkt.secret_key, keyid );
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
is_selfsig = 1;
}
}
if( opt.with_colons ) {
putchar(':');
if( sigrc != ' ' )
putchar(sigrc);
printf(":::%08lX%08lX:%s::::", (ulong)sig->keyid[0],
(ulong)sig->keyid[1], datestr_from_sig(sig));
}
else
printf("%c %08lX %s ",
sigrc, (ulong)sig->keyid[1], datestr_from_sig(sig));
if( sigrc == '%' )
printf("[%s] ", g10_errstr(rc2) );
else if( sigrc == '?' )
;
else if( is_selfsig ) {
if( opt.with_colons )
putchar(':');
fputs( sig->sig_class == 0x18? "[keybind]":"[selfsig]", stdout);
if( opt.with_colons )
putchar(':');
}
else {
p = get_user_id( sig->keyid, &n );
print_string( stdout, p, n, opt.with_colons );
m_free(p);
}
if( opt.with_colons )
printf(":%02x:", sig->sig_class );
putchar('\n');
}
else
log_error("invalid node with packet of type %d\n", node->pkt->pkttype);
}
int
proc_packets( IOBUF a )
{
CTX c = m_alloc_clear( sizeof *c );
int rc = do_proc_packets( c, a );
m_free( c );
return rc;
}
int
proc_signature_packets( IOBUF a, STRLIST signedfiles, const char *sigfilename )
{
CTX c = m_alloc_clear( sizeof *c );
int rc;
c->sigs_only = 1;
c->signed_data = signedfiles;
c->sigfilename = sigfilename;
rc = do_proc_packets( c, a );
m_free( c );
return rc;
}
int
proc_encryption_packets( IOBUF a )
{
CTX c = m_alloc_clear( sizeof *c );
int rc;
c->encrypt_only = 1;
rc = do_proc_packets( c, a );
m_free( c );
return rc;
}
int
do_proc_packets( CTX c, IOBUF a )
{
PACKET *pkt = m_alloc( sizeof *pkt );
int rc=0;
int newpkt;
c->iobuf = a;
init_packet(pkt);
while( (rc=parse_packet(a, pkt)) != -1 ) {
if( rc ) {
free_packet(pkt);
if( rc == G10ERR_INVALID_PACKET )
break;
continue;
}
newpkt = -1;
if( opt.list_packets ) {
switch( pkt->pkttype ) {
case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break;
case PKT_ENCRYPTED: proc_encrypted( c, pkt ); break;
case PKT_COMPRESSED: proc_compressed( c, pkt ); break;
default: newpkt = 0; break;
}
}
else if( c->sigs_only ) {
switch( pkt->pkttype ) {
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
case PKT_USER_ID:
case PKT_SYMKEY_ENC:
case PKT_PUBKEY_ENC:
case PKT_ENCRYPTED:
rc = G10ERR_UNEXPECTED;
goto leave;
case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break;
case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break;
case PKT_COMPRESSED: proc_compressed( c, pkt ); break;
case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
default: newpkt = 0; break;
}
}
else if( c->encrypt_only ) {
switch( pkt->pkttype ) {
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
case PKT_USER_ID:
rc = G10ERR_UNEXPECTED;
goto leave;
case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break;
case PKT_SYMKEY_ENC: proc_symkey_enc( c, pkt ); break;
case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break;
case PKT_ENCRYPTED: proc_encrypted( c, pkt ); break;
case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break;
case PKT_COMPRESSED: proc_compressed( c, pkt ); break;
case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
default: newpkt = 0; break;
}
}
else {
switch( pkt->pkttype ) {
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
release_list( c );
c->list = new_kbnode( pkt );
newpkt = 1;
break;
case PKT_PUBLIC_SUBKEY:
case PKT_SECRET_SUBKEY:
newpkt = add_subkey( c, pkt );
break;
case PKT_USER_ID: newpkt = add_user_id( c, pkt ); break;
case PKT_SIGNATURE: newpkt = add_signature( c, pkt ); break;
case PKT_PUBKEY_ENC: proc_pubkey_enc( c, pkt ); break;
case PKT_SYMKEY_ENC: proc_symkey_enc( c, pkt ); break;
case PKT_ENCRYPTED: proc_encrypted( c, pkt ); break;
case PKT_PLAINTEXT: proc_plaintext( c, pkt ); break;
case PKT_COMPRESSED: proc_compressed( c, pkt ); break;
case PKT_ONEPASS_SIG: newpkt = add_onepass_sig( c, pkt ); break;
default: newpkt = 0; break;
}
}
if( pkt->pkttype != PKT_SIGNATURE )
c->have_data = pkt->pkttype == PKT_PLAINTEXT;
if( newpkt == -1 )
;
else if( newpkt ) {
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
}
else
free_packet(pkt);
}
rc = 0;
leave:
release_list( c );
m_free(c->dek);
free_packet( pkt );
m_free( pkt );
free_md_filter_context( &c->mfx );
return rc;
}
static void
print_keyid( FILE *fp, u32 *keyid )
{
size_t n;
char *p = get_user_id( keyid, &n );
print_string( fp, p, n, opt.with_colons );
m_free(p);
}
static int
check_sig_and_print( CTX c, KBNODE node )
{
PKT_signature *sig = node->pkt->pkt.signature;
const char *astr, *tstr;
int rc;
if( opt.skip_verify ) {
log_info(_("signature verification suppressed\n"));
return 0;
}
tstr = asctimestamp(sig->timestamp);
astr = pubkey_algo_to_string( sig->pubkey_algo );
log_info(_("Signature made %.*s using %s key ID %08lX\n"),
(int)strlen(tstr), tstr, astr? astr: "?", (ulong)sig->keyid[1] );
rc = do_check_sig(c, node, NULL );
if( !rc || rc == G10ERR_BAD_SIGN ) {
char *us = get_long_user_id_string( sig->keyid );
write_status_text( rc? STATUS_BADSIG : STATUS_GOODSIG, us );
m_free(us);
log_info(rc? _("BAD signature from \"")
: _("Good signature from \""));
print_keyid( stderr, sig->keyid );
putc('\"', stderr);
putc('\n', stderr);
if( !rc )
rc = check_signatures_trust( sig );
if( rc )
g10_errors_seen = 1;
if( opt.batch && rc )
g10_exit(1);
}
else {
write_status( STATUS_ERRSIG );
log_error(_("Can't check signature: %s\n"), g10_errstr(rc) );
}
return rc;
}
/****************
* Process the tree which starts at node
*/
static void
proc_tree( CTX c, KBNODE node )
{
KBNODE n1;
int rc;
if( opt.list_packets )
return;
c->local_id = 0;
c->trustletter = ' ';
if( node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
merge_keys_and_selfsig( node );
list_node( c, node );
}
else if( node->pkt->pkttype == PKT_SECRET_KEY ) {
merge_keys_and_selfsig( node );
list_node( c, node );
}
else if( node->pkt->pkttype == PKT_ONEPASS_SIG ) {
/* check all signatures */
if( !c->have_data ) {
free_md_filter_context( &c->mfx );
/* prepare to create all requested message digests */
c->mfx.md = md_open(0, 0);
/* fixme: why looking for the signature packet and not 1passpacket*/
for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); ) {
md_enable( c->mfx.md, n1->pkt->pkt.signature->digest_algo);
}
/* ask for file and hash it */
if( c->sigs_only )
rc = hash_datafiles( c->mfx.md, c->signed_data, c->sigfilename,
n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 );
else
rc = ask_for_detached_datafile( &c->mfx,
iobuf_get_fname(c->iobuf));
if( rc ) {
log_error("can't hash datafile: %s\n", g10_errstr(rc));
return;
}
}
for( n1 = node; (n1 = find_next_kbnode(n1, PKT_SIGNATURE )); )
check_sig_and_print( c, n1 );
}
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
PKT_signature *sig = node->pkt->pkt.signature;
if( !c->have_data ) {
free_md_filter_context( &c->mfx );
c->mfx.md = md_open(sig->digest_algo, 0);
if( c->sigs_only )
rc = hash_datafiles( c->mfx.md, c->signed_data, c->sigfilename,
sig->sig_class == 0x01 );
else
rc = ask_for_detached_datafile( &c->mfx,
iobuf_get_fname(c->iobuf));
if( rc ) {
log_error("can't hash datafile: %s\n", g10_errstr(rc));
return;
}
}
else
log_info(_("old style (PGP 2.x) signature\n"));
check_sig_and_print( c, node );
}
else
log_error(_("invalid root packet detected in proc_tree()\n"));
}
diff --git a/g10/mdfilter.c b/g10/mdfilter.c
index a18636e8b..1d26e20ba 100644
--- a/g10/mdfilter.c
+++ b/g10/mdfilter.c
@@ -1,75 +1,75 @@
/* mdfilter.c - filter data and calculate a message digest
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "errors.h"
#include "iobuf.h"
#include "memory.h"
#include "util.h"
#include "filter.h"
/****************
* This filter is used to collect a message digest
*/
int
md_filter( void *opaque, int control,
IOBUF a, byte *buf, size_t *ret_len)
{
size_t size = *ret_len;
md_filter_context_t *mfx = opaque;
int i, c, rc=0;
if( control == IOBUFCTRL_UNDERFLOW ) {
if( mfx->maxbuf_size && size > mfx->maxbuf_size )
size = mfx->maxbuf_size;
for(i=0; i < size; i++ ) {
if( (c = iobuf_get(a)) == -1 )
break;
buf[i] = c;
}
if( i )
md_write(mfx->md, buf, i );
else
rc = -1; /* eof */
*ret_len = i;
}
else if( control == IOBUFCTRL_DESC )
*(char**)buf = "md_filter";
return rc;
}
void
free_md_filter_context( md_filter_context_t *mfx )
{
md_close(mfx->md);
mfx->md = NULL;
mfx->maxbuf_size = 0;
}
diff --git a/g10/misc.c b/g10/misc.c
index e7990475b..e533966d9 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -1,247 +1,247 @@
/* misc.c - miscellaneous functions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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>
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
#include <asm/sysinfo.h>
#include <asm/unistd.h>
#endif
#ifdef HAVE_SETRLIMIT
#include <sys/time.h>
#include <sys/resource.h>
#endif
#include "util.h"
#include "main.h"
#include "options.h"
#include "i18n.h"
const char *g10m_revision_string(int);
const char *g10c_revision_string(int);
const char *g10u_revision_string(int);
volatile void
pull_in_libs(void)
{
g10m_revision_string(0);
g10c_revision_string(0);
g10u_revision_string(0);
}
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
#warning using trap_unaligned
static int
setsysinfo(unsigned long op, void *buffer, unsigned long size,
int *start, void *arg, unsigned long flag)
{
return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
}
void
trap_unaligned(void)
{
unsigned int buf[2];
buf[0] = SSIN_UACPROC;
buf[1] = UAC_SIGBUS | UAC_NOPRINT;
setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
}
#else
void
trap_unaligned(void)
{ /* dummy */
}
#endif
void
disable_core_dumps()
{
#ifdef HAVE_SETRLIMIT
struct rlimit limit;
limit.rlim_cur = 0;
limit.rlim_max = 0;
if( setrlimit( RLIMIT_CORE, &limit ) )
log_fatal(_("can't disable core dumps: %s\n"), strerror(errno) );
#else
log_info(_("WARNING: Program may create a core file!\n"));
#endif
}
u16
checksum_u16( unsigned n )
{
u16 a;
a = (n >> 8) & 0xff;
if( opt.emulate_bugs & EMUBUG_GPGCHKSUM ) {
a |= n & 0xff;
log_debug("csum_u16 emulated for n=%u\n", n);
}
else
a += n & 0xff;
return a;
}
static u16
checksum_u16_nobug( unsigned n )
{
u16 a;
a = (n >> 8) & 0xff;
a += n & 0xff;
return a;
}
u16
checksum( byte *p, unsigned n )
{
u16 a;
for(a=0; n; n-- )
a += *p++;
return a;
}
u16
checksum_mpi( MPI a )
{
u16 csum;
byte *buffer;
unsigned nbytes;
unsigned nbits;
buffer = mpi_get_buffer( a, &nbytes, NULL );
/* some versions of gpg encode wrong values for the length of an mpi
* so that mpi_get_nbits() which counts the mpi yields another (shorter)
* value than the one store with the mpi. mpi_get_nbit_info() returns
* this stored value if it is still available.
*/
if( opt.emulate_bugs & EMUBUG_GPGCHKSUM )
nbits = 0;
else
nbits = mpi_get_nbit_info(a);
if( !nbits )
nbits = mpi_get_nbits(a);
csum = checksum_u16( nbits );
csum += checksum( buffer, nbytes );
m_free( buffer );
return csum;
}
/****************
* This is the correct function
*/
u16
checksum_mpi_counted_nbits( MPI a )
{
u16 csum;
byte *buffer;
unsigned nbytes;
unsigned nbits;
buffer = mpi_get_buffer( a, &nbytes, NULL );
nbits = mpi_get_nbits(a);
mpi_set_nbit_info(a,nbits);
csum = checksum_u16_nobug( nbits );
csum += checksum( buffer, nbytes );
m_free( buffer );
return csum;
}
u32
buffer_to_u32( const byte *buffer )
{
unsigned long a;
a = *buffer << 24;
a |= buffer[1] << 16;
a |= buffer[2] << 8;
a |= buffer[3];
return a;
}
static void
no_exp_algo(void)
{
static int did_note = 0;
if( !did_note ) {
did_note = 1;
log_info(_("Experimental algorithms should not be used!\n"));
}
}
void
print_pubkey_algo_note( int algo )
{
if( algo >= 100 && algo <= 110 )
no_exp_algo();
else if( is_RSA( algo ) ) {
static int did_note = 0;
if( !did_note ) {
did_note = 1;
log_info(_("RSA keys are deprecated; please consider "
"creating a new key and use this key in the future\n"));
}
}
}
void
print_cipher_algo_note( int algo )
{
if( algo >= 100 && algo <= 110 )
no_exp_algo();
else if( algo == CIPHER_ALGO_3DES
|| algo == CIPHER_ALGO_CAST5
|| algo == CIPHER_ALGO_BLOWFISH
)
;
else {
static int did_note = 0;
if( !did_note ) {
did_note = 1;
log_info(_("This cipher algorithm is depreciated; "
"please use a more standard one!\n"));
}
}
}
void
print_digest_algo_note( int algo )
{
if( algo >= 100 && algo <= 110 )
no_exp_algo();
}
diff --git a/g10/openfile.c b/g10/openfile.c
index a6d24ed38..1ffeeedee 100644
--- a/g10/openfile.c
+++ b/g10/openfile.c
@@ -1,184 +1,184 @@
/* openfile.c
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <errno.h>
#include <unistd.h>
#include "util.h"
#include "memory.h"
#include "ttyio.h"
#include "options.h"
#include "main.h"
#include "status.h"
#include "i18n.h"
/****************
* Check whether FNAME exists and ask if it's okay to overwrite an
* existing one.
* Returns: True: it's okay to overwrite or the file does not exist
* False: Do not overwrite
*/
int
overwrite_filep( const char *fname )
{
if( !fname || (*fname == '-' && !fname[1]) )
return 1; /* writing to stdout is always okay */
if( access( fname, F_OK ) )
return 1; /* does not exist */
/* fixme: add some backup stuff in case of overwrite */
if( opt.answer_yes )
return 1;
if( opt.answer_no || opt.batch )
return 0; /* do not overwrite */
tty_printf(_("File '%s' exists. "), fname);
if( cpr_get_answer_is_yes("openfile.overwrite.okay",
_("Overwrite (y/N)? ")) )
return 1;
return 0;
}
/****************
* Make an output filename for the inputfile INAME.
* Returns an IOBUF and an errorcode
* Mode 0 = use ".gpg"
* 1 = use ".asc"
* 2 = use ".sig"
*/
int
open_outfile( const char *iname, int mode, IOBUF *a )
{
int rc = 0;
*a = NULL;
if( (!iname || (*iname=='-' && !iname[1])) && !opt.outfile ) {
if( !(*a = iobuf_create(NULL)) ) {
log_error(_("%s: can't open: %s\n"), "[stdout]", strerror(errno) );
rc = G10ERR_CREATE_FILE;
}
else if( opt.verbose )
log_info(_("writing to stdout\n"));
}
else {
char *buf=NULL;
const char *name;
if( opt.outfile )
name = opt.outfile;
else {
buf = m_alloc(strlen(iname)+4+1);
strcpy(stpcpy(buf,iname), mode==1 ? ".asc" :
mode==2 ? ".sig" : ".gpg");
name = buf;
}
if( overwrite_filep( name ) ) {
if( !(*a = iobuf_create( name )) ) {
log_error(_("%s: can't create: %s\n"), name, strerror(errno) );
rc = G10ERR_CREATE_FILE;
}
else if( opt.verbose )
log_info(_("writing to '%s'\n"), name );
}
else
rc = G10ERR_FILE_EXISTS;
m_free(buf);
}
return rc;
}
/****************
* Try to open a file without the extension ".sig" or ".asc"
* Return NULL if such a file is not available.
*/
IOBUF
open_sigfile( const char *iname )
{
IOBUF a = NULL;
size_t len;
if( iname && !(*iname == '-' && !iname[1]) ) {
len = strlen(iname);
if( len > 4 && ( !strcmp(iname + len - 4, ".sig")
|| !strcmp(iname + len - 4, ".asc")) ) {
char *buf;
buf = m_strdup(iname);
buf[len-4] = 0 ;
a = iobuf_open( buf );
if( opt.verbose )
log_info(_("assuming signed data in '%s'\n"), buf );
m_free(buf);
}
}
return a;
}
/****************
* Copy the option file skeleton to the given directory.
*/
void
copy_options_file( const char *destdir )
{
const char *datadir = GNUPG_DATADIR;
char *fname;
FILE *src, *dst;
int linefeeds=0;
int c;
fname = m_alloc( strlen(datadir) + strlen(destdir) + 15 );
strcpy(stpcpy(fname, datadir), "/options.skel" );
src = fopen( fname, "r" );
if( !src ) {
log_error(_("%s: can't open: %s\n"), fname, strerror(errno) );
m_free(fname);
return;
}
strcpy(stpcpy(fname, destdir), "/options" );
dst = fopen( fname, "w" );
if( !dst ) {
log_error(_("%s: can't create: %s\n"), fname, strerror(errno) );
fclose( src );
m_free(fname);
return;
}
while( (c=getc(src)) != EOF ) {
if( linefeeds < 3 ) {
if( c == '\n' )
linefeeds++;
}
else
putc( c, dst );
}
fclose( dst );
fclose( src );
log_info(_("%s: new options file created\n"), fname );
m_free(fname);
}
diff --git a/g10/options.h b/g10/options.h
index b6b1cd2de..e6491864e 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -1,93 +1,93 @@
/* options.h
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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_OPTIONS_H
#define G10_OPTIONS_H
#undef ENABLE_COMMENT_PACKETS /* don't create comment packets */
struct {
int verbose;
int quiet;
unsigned debug;
int armor;
int compress;
char *outfile;
int textmode;
int batch; /* run in batch mode */
int answer_yes; /* answer yes on most questions */
int answer_no; /* answer no on most questions */
int check_sigs; /* check key signatures */
int with_colons;
int fingerprint; /* list fingerprints */
int list_sigs; /* list signatures */
int no_armor;
int list_packets; /* list-packets mode */
int def_cipher_algo;
int force_v3_sigs;
int def_digest_algo;
int def_compress_algo;
const char *def_secret_key;
int no_comment;
int marginals_needed;
int completes_needed;
int max_cert_depth;
const char *homedir;
int skip_verify;
int compress_keys;
int compress_sigs;
int always_trust;
int rfc1991;
unsigned emulate_bugs; /* bug emulation flags EMUBUG_xxxx */
int shm_coprocess;
const char *set_filename;
const char *comment_string;
int throw_keyid;
int s2k_mode;
int s2k_digest_algo;
int s2k_cipher_algo;
int not_dash_escaped;
int escape_from;
int lock_once;
} opt;
#define EMUBUG_GPGCHKSUM 1
#define DBG_PACKET_VALUE 1 /* debug packet reading/writing */
#define DBG_MPI_VALUE 2 /* debug mpi details */
#define DBG_CIPHER_VALUE 4 /* debug cipher handling */
/* (may reveal sensitive data) */
#define DBG_FILTER_VALUE 8 /* debug internal filter handling */
#define DBG_IOBUF_VALUE 16 /* debug iobuf stuff */
#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */
#define DBG_CACHE_VALUE 64 /* debug the cacheing */
#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */
#define DBG_TRUST_VALUE 256 /* debug the trustdb */
#define DBG_PACKET (opt.debug & DBG_PACKET_VALUE)
#define DBG_FILTER (opt.debug & DBG_FILTER_VALUE)
#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
#define DBG_TRUST (opt.debug & DBG_TRUST_VALUE)
#endif /*G10_OPTIONS_H*/
diff --git a/g10/options.skel b/g10/options.skel
index 82916826c..1ad93b487 100644
--- a/g10/options.skel
+++ b/g10/options.skel
@@ -1,58 +1,58 @@
These first three lines are not copied to the options file in
the users home directory.
$Id$
# Options for GnuPG
#
# Unless you you specify which option file to use (with the
# commandline option "--options filename"), GnuPG uses the
# file ~/.gnupg/options by default.
#
# An option file can contain all long options which are
# available in GnuPG. If the first non white space character of
# a line is a '#', this line is ignored. Empty lines are also
# ignored.
#
# See the man page for a list of options.
# Uncomment the next line to get rid of the copyright notice
#no-greeting
# If you have more than 1 secret key in your keyring, you may want
# to uncomment the following option and set your preffered keyid
# default-key 621CC013
# The next option is enabled because this one is needed for interoperation
# with PGP 5 users. To enable full OpenPGP compliance you have to remove
# this option.
force-v3-sigs
# Because some mailers change lines starting with "From " to ">From "
# it is good to handle such lines in a special way when creating
# cleartext signatures; all other PGP versions it this way too.
# To enable full OpenPGP compliance you have to remove this option.
-escape_from_lines
+escape-from-lines
# If you do not use the Latin-1 (ISO-8859-1) charset, you should
# tell GnuPG which is the native character set. Please check
# the man page for supported character sets.
#charset koi8-r
# You may define aliases like this:
# alias mynames -u 0x12345678 -u 0x456789ab -z 9
# everytime you use --mynames, it will be expanded to the options
# in the above defintion. The name of the alias may not be abbreviated.
# NOTE: This is not yet implemented
# lock the file only once for the lifetime of a process.
# if you do not define this, the lock will be obtained and released
# every time it is needed - normally this is not needed.
lock-once
# If you are not running one of the free operation systems
# you probably have to uncomment the next line:
#load-extension rndunix
diff --git a/g10/packet.h b/g10/packet.h
index e047fd944..1f5f57416 100644
--- a/g10/packet.h
+++ b/g10/packet.h
@@ -1,321 +1,338 @@
/* packet.h - packet read/write stuff
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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_PACKET_H
#define G10_PACKET_H
#include "types.h"
#include "iobuf.h"
#include "mpi.h"
#include "cipher.h"
#include "filter.h"
+#define DEBUG_PARSE_PACKET 1
+
typedef enum {
PKT_NONE =0,
PKT_PUBKEY_ENC =1, /* public key encrypted packet */
PKT_SIGNATURE =2, /* secret key encrypted packet */
PKT_SYMKEY_ENC =3, /* session key packet (OpenPGP)*/
PKT_ONEPASS_SIG =4, /* one pass sig packet (OpenPGP)*/
PKT_SECRET_KEY =5, /* secret key */
PKT_PUBLIC_KEY =6, /* public key */
PKT_SECRET_SUBKEY =7, /* secret subkey (OpenPGP) */
PKT_COMPRESSED =8, /* compressed data packet */
PKT_ENCRYPTED =9, /* conventional encrypted data */
PKT_MARKER =10, /* marker packet (OpenPGP) */
PKT_PLAINTEXT =11, /* plaintext data with filename and mode */
PKT_RING_TRUST =12, /* keyring trust packet */
PKT_USER_ID =13, /* user id packet */
PKT_PUBLIC_SUBKEY =14, /* public subkey (OpenPGP) */
PKT_OLD_COMMENT =16, /* comment packet from an OpenPGP draft */
PKT_COMMENT =61 /* new comment packet (private) */
} pkttype_t;
typedef struct packet_struct PACKET;
typedef struct {
byte mode;
byte hash_algo;
byte salt[8];
u32 count;
} STRING2KEY;
typedef struct {
byte version;
byte cipher_algo; /* cipher algorithm used */
STRING2KEY s2k;
byte seskeylen; /* keylength in byte or 0 for no seskey */
byte seskey[1];
} PKT_symkey_enc;
typedef struct {
u32 keyid[2]; /* 64 bit keyid */
byte version;
byte pubkey_algo; /* algorithm used for public key scheme */
byte throw_keyid;
MPI data[PUBKEY_MAX_NENC];
} PKT_pubkey_enc;
typedef struct {
u32 keyid[2]; /* 64 bit keyid */
byte sig_class; /* sig classification */
byte digest_algo; /* algorithm used for digest */
byte pubkey_algo; /* algorithm used for public key scheme */
byte last; /* a stupid flag */
} PKT_onepass_sig;
typedef struct {
ulong local_id; /* internal use, valid if > 0 */
struct {
unsigned checked:1; /* signature has been checked */
unsigned valid:1; /* signature is good (if checked is set) */
unsigned unknown_critical:1;
} flags;
u32 keyid[2]; /* 64 bit keyid */
u32 timestamp; /* signature made */
byte version;
byte sig_class; /* sig classification, append for MD calculation*/
byte pubkey_algo; /* algorithm used for public key scheme */
/* (PUBKEY_ALGO_xxx) */
byte digest_algo; /* algorithm used for digest (DIGEST_ALGO_xxxx) */
byte *hashed_data; /* all subpackets with hashed data (v4 only) */
byte *unhashed_data; /* ditto for unhashed data */
byte digest_start[2]; /* first 2 bytes of the digest */
MPI data[PUBKEY_MAX_NSIG];
} PKT_signature;
/****************
* Note about the pkey/skey elements: We assume that the secret keys
* has the same elemts as the public key at the begin of the array, so
* that npkey < nskey and it is possible to compare the secret and
* public keys by comparing the first npkey elements of pkey againts skey.
*/
typedef struct {
u32 timestamp; /* key made */
u32 expiredate; /* expires at this date or 0 if not at all */
byte hdrbytes; /* number of header bytes */
byte version;
byte pubkey_algo; /* algorithm used for public key scheme */
byte pubkey_usage; /* for now only used to pass it to getkey() */
ulong local_id; /* internal use, valid if > 0 */
u32 keyid[2]; /* calculated by keyid_from_pk() */
byte *namehash; /* if != NULL: found by this name */
MPI pkey[PUBKEY_MAX_NPKEY];
} PKT_public_key;
typedef struct {
u32 timestamp; /* key made */
u32 expiredate; /* expires at this date or 0 if not at all */
byte hdrbytes; /* number of header bytes */
byte version;
byte pubkey_algo; /* algorithm used for public key scheme */
byte pubkey_usage;
byte is_protected; /* The secret info is protected and must */
/* be decrypted before use, the protected */
/* MPIs are simply (void*) pointers to memory */
/* and should never be passed to a mpi_xxx() */
struct {
byte algo; /* cipher used to protect the secret information*/
STRING2KEY s2k;
byte iv[8]; /* initialization vector for CFB mode */
} protect;
MPI skey[PUBKEY_MAX_NSKEY];
u16 csum; /* checksum */
} PKT_secret_key;
typedef struct {
int len; /* length of data */
char data[1];
} PKT_comment;
typedef struct {
int len; /* length of the name */
char name[1];
} PKT_user_id;
typedef struct {
u32 len; /* reserved */
byte new_ctb;
byte algorithm;
IOBUF buf; /* IOBUF reference */
} PKT_compressed;
typedef struct {
u32 len; /* length of encrypted data */
byte new_ctb;
IOBUF buf; /* IOBUF reference */
} PKT_encrypted;
typedef struct {
u32 len; /* length of encrypted data */
IOBUF buf; /* IOBUF reference */
byte new_ctb;
int mode;
u32 timestamp;
int namelen;
char name[1];
} PKT_plaintext;
/* combine all packets into a union */
struct packet_struct {
pkttype_t pkttype;
union {
void *generic;
PKT_symkey_enc *symkey_enc; /* PKT_SYMKEY_ENC */
PKT_pubkey_enc *pubkey_enc; /* PKT_PUBKEY_ENC */
PKT_onepass_sig *onepass_sig; /* PKT_ONEPASS_SIG */
PKT_signature *signature; /* PKT_SIGNATURE */
PKT_public_key *public_key; /* PKT_PUBLIC_[SUB)KEY */
PKT_secret_key *secret_key; /* PKT_SECRET_[SUB]KEY */
PKT_comment *comment; /* PKT_COMMENT */
PKT_user_id *user_id; /* PKT_USER_ID */
PKT_compressed *compressed; /* PKT_COMPRESSED */
PKT_encrypted *encrypted; /* PKT_ENCRYPTED */
PKT_plaintext *plaintext; /* PKT_PLAINTEXT */
} pkt;
};
#define init_packet(a) do { (a)->pkttype = 0; \
(a)->pkt.generic = NULL; \
} while(0)
typedef enum {
SIGSUBPKT_TEST_CRITICAL=-3,
SIGSUBPKT_LIST_UNHASHED=-2,
SIGSUBPKT_LIST_HASHED =-1,
SIGSUBPKT_NONE = 0,
SIGSUBPKT_SIG_CREATED = 2, /* signature creation time */
SIGSUBPKT_SIG_EXPIRE = 3, /* signature expiration time */
SIGSUBPKT_EXPORTABLE = 4, /* exportable */
SIGSUBPKT_TRUST = 5, /* trust signature */
SIGSUBPKT_REGEXP = 6, /* regular expression */
SIGSUBPKT_REVOCABLE = 7, /* revocable */
SIGSUBPKT_KEY_EXPIRE = 9, /* key expiration time */
SIGSUBPKT_ARR =10, /* additional recipient request */
SIGSUBPKT_PREF_SYM =11, /* preferred symmetric algorithms */
SIGSUBPKT_REV_KEY =12, /* revocation key */
SIGSUBPKT_ISSUER =16, /* issuer key ID */
SIGSUBPKT_NOTATION =20, /* notation data */
SIGSUBPKT_PREF_HASH =21, /* preferred hash algorithms */
SIGSUBPKT_PREF_COMPR =22, /* preferred compression algorithms */
SIGSUBPKT_KS_FLAGS =23, /* key server preferences */
SIGSUBPKT_PREF_KS =24, /* preferred key server */
SIGSUBPKT_PRIMARY_UID =25, /* primary user id */
SIGSUBPKT_POLICY =26, /* policy URL */
SIGSUBPKT_KEY_FLAGS =27, /* key flags */
SIGSUBPKT_SIGNERS_UID =28, /* signer's user id */
SIGSUBPKT_PRIV_ADD_SIG =101 /* signatur is also valid for this uid */
} sigsubpkttype_t;
/*-- mainproc.c --*/
int proc_packets( IOBUF a );
int proc_signature_packets( IOBUF a, STRLIST signedfiles, const char *sigfile );
int proc_encryption_packets( IOBUF a );
int list_packets( IOBUF a );
/*-- parse-packet.c --*/
int set_packet_list_mode( int mode );
+
+#if DEBUG_PARSE_PACKET
+int dbg_search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos, const char* file, int lineno );
+int dbg_parse_packet( IOBUF inp, PACKET *ret_pkt, const char* file, int lineno );
+int dbg_copy_all_packets( IOBUF inp, IOBUF out, const char* file, int lineno );
+int dbg_copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff, const char* file, int lineno );
+int dbg_skip_some_packets( IOBUF inp, unsigned n, const char* file, int lineno );
+#define search_packet( a,b,c,d ) dbg_search_packet( (a), (b), (c), (d), __FILE__, __LINE__ )
+#define parse_packet( a, b ) dbg_parse_packet( (a), (b), __FILE__, __LINE__ )
+#define copy_all_packets( a,b ) dbg_copy_all_packets((a),(b), __FILE__, __LINE__ )
+#define copy_some_packets( a,b,c ) dbg_copy_some_packets((a),(b),(c), __FILE__, __LINE__ )
+#define skip_some_packets( a,b ) dbg_skip_some_packets((a),(b), __FILE__, __LINE__ )
+#else
int search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos );
int parse_packet( IOBUF inp, PACKET *ret_pkt);
int copy_all_packets( IOBUF inp, IOBUF out );
int copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff );
int skip_some_packets( IOBUF inp, unsigned n );
+#endif
+
const byte *parse_sig_subpkt( const byte *buffer,
sigsubpkttype_t reqtype, size_t *ret_n );
const byte *parse_sig_subpkt2( PKT_signature *sig,
sigsubpkttype_t reqtype, size_t *ret_n );
/*-- build-packet.c --*/
int build_packet( IOBUF inp, PACKET *pkt );
u32 calc_packet_length( PACKET *pkt );
void hash_public_key( MD_HANDLE md, PKT_public_key *pk );
void build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type,
const byte *buffer, size_t buflen );
void build_sig_subpkt_from_sig( PKT_signature *sig );
/*-- free-packet.c --*/
void free_symkey_enc( PKT_symkey_enc *enc );
void free_pubkey_enc( PKT_pubkey_enc *enc );
void free_seckey_enc( PKT_signature *enc );
int digest_algo_from_sig( PKT_signature *sig );
void release_public_key_parts( PKT_public_key *pk );
void free_public_key( PKT_public_key *key );
void release_secret_key_parts( PKT_secret_key *sk );
void free_secret_key( PKT_secret_key *sk );
void free_user_id( PKT_user_id *uid );
void free_comment( PKT_comment *rem );
void free_packet( PACKET *pkt );
PKT_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s );
PKT_public_key *copy_public_key_new_namehash( PKT_public_key *d,
PKT_public_key *s,
const byte *namehash );
PKT_secret_key *copy_secret_key( PKT_secret_key *d, PKT_secret_key *s );
PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s );
PKT_user_id *copy_user_id( PKT_user_id *d, PKT_user_id *s );
int cmp_public_keys( PKT_public_key *a, PKT_public_key *b );
int cmp_secret_keys( PKT_secret_key *a, PKT_secret_key *b );
int cmp_signatures( PKT_signature *a, PKT_signature *b );
int cmp_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk );
int cmp_user_ids( PKT_user_id *a, PKT_user_id *b );
/*-- sig-check.c --*/
int signature_check( PKT_signature *sig, MD_HANDLE digest );
/*-- seckey-cert.c --*/
int is_secret_key_protected( PKT_secret_key *sk );
int check_secret_key( PKT_secret_key *sk, int retries );
int protect_secret_key( PKT_secret_key *sk, DEK *dek );
/*-- pubkey-enc.c --*/
int get_session_key( PKT_pubkey_enc *k, DEK *dek );
/*-- compress.c --*/
int handle_compressed( PKT_compressed *cd,
int (*callback)(IOBUF, void *), void *passthru );
/*-- encr-data.c --*/
int decrypt_data( PKT_encrypted *ed, DEK *dek );
int encrypt_data( PKT_encrypted *ed, DEK *dek );
/*-- plaintext.c --*/
int handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
int nooutput, int clearsig );
int ask_for_detached_datafile( md_filter_context_t *mfx, const char *inname );
/*-- comment.c --*/
int write_comment( IOBUF out, const char *s );
/*-- sign.c --*/
int make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
PKT_user_id *uid, PKT_public_key *subpk,
PKT_secret_key *sk,
int sigclass, int digest_algo,
int (*mksubpkt)(PKT_signature *, void *),
void *opaque );
/*-- keygen.c --*/
PKT_user_id *generate_user_id(void);
#endif /*G10_PACKET_H*/
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index 29e4fc4e6..5bee45b32 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -1,1473 +1,1564 @@
/* parse-packet.c - read packets
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "packet.h"
#include "iobuf.h"
#include "mpi.h"
#include "util.h"
#include "cipher.h"
#include "memory.h"
#include "filter.h"
#include "options.h"
#include "main.h"
#include "i18n.h"
static int mpi_print_mode = 0;
static int list_mode = 0;
static int parse( IOBUF inp, PACKET *pkt, int reqtype,
- ulong *retpos, int *skip, IOBUF out, int do_skip );
+ ulong *retpos, int *skip, IOBUF out, int do_skip
+ #ifdef DEBUG_PARSE_PACKET
+ ,const char *dbg_w, const char *dbg_f, int dbg_l
+ #endif
+ );
static int copy_packet( IOBUF inp, IOBUF out, int pkttype,
unsigned long pktlen );
static void skip_packet( IOBUF inp, int pkttype, unsigned long pktlen );
static void skip_rest( IOBUF inp, unsigned long pktlen );
static void *read_rest( IOBUF inp, ulong *r_pktlen );
static int parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
static int parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
static int parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
PKT_signature *sig );
static int parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
PKT_onepass_sig *ops );
static int parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
byte *hdr, int hdrlen, PACKET *packet );
static int parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
static int parse_comment( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet );
static void parse_trust( IOBUF inp, int pkttype, unsigned long pktlen );
static int parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet, int new_ctb);
static int parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet, int new_ctb );
static int parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *packet, int new_ctb);
static unsigned short
read_16(IOBUF inp)
{
unsigned short a;
a = iobuf_get_noeof(inp) << 8;
a |= iobuf_get_noeof(inp);
return a;
}
static unsigned long
read_32(IOBUF inp)
{
unsigned long a;
a = iobuf_get_noeof(inp) << 24;
a |= iobuf_get_noeof(inp) << 16;
a |= iobuf_get_noeof(inp) << 8;
a |= iobuf_get_noeof(inp);
return a;
}
int
set_packet_list_mode( int mode )
{
int old = list_mode;
list_mode = mode;
mpi_print_mode = DBG_MPI;
return old;
}
static void
unknown_pubkey_warning( int algo )
{
static byte unknown_pubkey_algos[256];
algo &= 0xff;
if( !unknown_pubkey_algos[algo] ) {
if( opt.verbose )
log_info(_("can't handle public key algorithm %d\n"), algo );
unknown_pubkey_algos[algo] = 1;
}
}
/****************
* Parse a Packet and return it in packet
* Returns: 0 := valid packet in pkt
* -1 := no more packets
* >0 := error
* Note: The function may return an error and a partly valid packet;
* caller must free this packet.
*/
+#ifdef DEBUG_PARSE_PACKET
+int
+dbg_parse_packet( IOBUF inp, PACKET *pkt, const char *dbg_f, int dbg_l )
+{
+ int skip, rc;
+
+ do {
+ rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0, "parse", dbg_f, dbg_l );
+ } while( skip );
+ return rc;
+}
+#else
int
parse_packet( IOBUF inp, PACKET *pkt )
{
int skip, rc;
do {
rc = parse( inp, pkt, 0, NULL, &skip, NULL, 0 );
} while( skip );
return rc;
}
+#endif
/****************
* Like parse packet, but only return packets of the given type.
*/
+#ifdef DEBUG_PARSE_PACKET
+int
+dbg_search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos,
+ const char *dbg_f, int dbg_l )
+{
+ int skip, rc;
+
+ do {
+ rc = parse( inp, pkt, pkttype, retpos, &skip, NULL, 0, "search", dbg_f, dbg_l );
+ } while( skip );
+ return rc;
+}
+#else
int
search_packet( IOBUF inp, PACKET *pkt, int pkttype, ulong *retpos )
{
int skip, rc;
do {
rc = parse( inp, pkt, pkttype, retpos, &skip, NULL, 0 );
} while( skip );
return rc;
}
+#endif
/****************
* Copy all packets from INP to OUT, thereby removing unused spaces.
*/
+#ifdef DEBUG_PARSE_PACKET
+int
+dbg_copy_all_packets( IOBUF inp, IOBUF out,
+ const char *dbg_f, int dbg_l )
+{
+ PACKET pkt;
+ int skip, rc=0;
+ do {
+ init_packet(&pkt);
+ } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0, "copy", dbg_f, dbg_l )));
+ return rc;
+}
+#else
int
copy_all_packets( IOBUF inp, IOBUF out )
{
PACKET pkt;
int skip, rc=0;
do {
init_packet(&pkt);
} while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )));
return rc;
}
+#endif
/****************
* Copy some packets from INP to OUT, thereby removing unused spaces.
* Stop at offset STOPoff (i.e. don't copy packets at this or later offsets)
*/
+#ifdef DEBUG_PARSE_PACKET
+int
+dbg_copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff,
+ const char *dbg_f, int dbg_l )
+{
+ PACKET pkt;
+ int skip, rc=0;
+ do {
+ if( iobuf_tell(inp) >= stopoff )
+ return 0;
+ init_packet(&pkt);
+ } while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0,
+ "some", dbg_f, dbg_l )) );
+ return rc;
+}
+#else
int
copy_some_packets( IOBUF inp, IOBUF out, ulong stopoff )
{
PACKET pkt;
int skip, rc=0;
do {
if( iobuf_tell(inp) >= stopoff )
return 0;
init_packet(&pkt);
} while( !(rc = parse( inp, &pkt, 0, NULL, &skip, out, 0 )) );
return rc;
}
+#endif
/****************
* Skip over N packets
*/
+#ifdef DEBUG_PARSE_PACKET
+int
+dbg_skip_some_packets( IOBUF inp, unsigned n,
+ const char *dbg_f, int dbg_l )
+{
+ int skip, rc=0;
+ PACKET pkt;
+
+ for( ;n && !rc; n--) {
+ init_packet(&pkt);
+ rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1, "skip", dbg_f, dbg_l );
+ }
+ return rc;
+}
+#else
int
skip_some_packets( IOBUF inp, unsigned n )
{
int skip, rc=0;
PACKET pkt;
for( ;n && !rc; n--) {
init_packet(&pkt);
rc = parse( inp, &pkt, 0, NULL, &skip, NULL, 1 );
}
return rc;
}
-
+#endif
/****************
* Parse packet. Set the variable skip points to to 1 if the packet
* should be skipped; this is the case if either there is a
* requested packet type and the parsed packet doesn't match or the
* packet-type is 0, indicating deleted stuff.
* if OUT is not NULL, a special copymode is used.
*/
static int
parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
- int *skip, IOBUF out, int do_skip )
+ int *skip, IOBUF out, int do_skip
+#ifdef DEBUG_PARSE_PACKET
+ ,const char *dbg_w, const char *dbg_f, int dbg_l
+#endif
+ )
{
int rc=0, c, ctb, pkttype, lenbytes;
unsigned long pktlen;
byte hdr[8];
int hdrlen;
int new_ctb = 0;
*skip = 0;
assert( !pkt->pkt.generic );
if( retpos )
*retpos = iobuf_tell(inp);
+
if( (ctb = iobuf_get(inp)) == -1 ) {
rc = -1;
goto leave;
}
hdrlen=0;
hdr[hdrlen++] = ctb;
if( !(ctb & 0x80) ) {
- log_error("%s: invalid packet (ctb=%02x)\n", iobuf_where(inp), ctb );
+ log_error("%s: invalid packet (ctb=%02x) near %lu\n",
+ iobuf_where(inp), ctb, iobuf_tell(inp) );
rc = G10ERR_INVALID_PACKET;
goto leave;
}
pktlen = 0;
new_ctb = !!(ctb & 0x40);
if( new_ctb ) {
pkttype = ctb & 0x3f;
if( (c = iobuf_get(inp)) == -1 ) {
log_error("%s: 1st length byte missing\n", iobuf_where(inp) );
rc = G10ERR_INVALID_PACKET;
goto leave;
}
hdr[hdrlen++] = c;
if( c < 192 )
pktlen = c;
else if( c < 224 ) {
pktlen = (c - 192) * 256;
if( (c = iobuf_get(inp)) == -1 ) {
log_error("%s: 2nd length byte missing\n", iobuf_where(inp) );
rc = G10ERR_INVALID_PACKET;
goto leave;
}
hdr[hdrlen++] = c;
pktlen += c + 192;
}
else if( c == 255 ) {
pktlen = (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 24;
pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 16;
pktlen |= (hdr[hdrlen++] = iobuf_get_noeof(inp)) << 8;
if( (c = iobuf_get(inp)) == -1 ) {
log_error("%s: 4 byte length invalid\n", iobuf_where(inp) );
rc = G10ERR_INVALID_PACKET;
goto leave;
}
pktlen |= (hdr[hdrlen++] = c );
}
else { /* partial body length */
iobuf_set_partial_block_mode(inp, c & 0xff);
pktlen = 0;/* to indicate partial length */
}
}
else {
pkttype = (ctb>>2)&0xf;
lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
if( !lenbytes ) {
pktlen = 0; /* don't know the value */
if( pkttype != PKT_COMPRESSED )
iobuf_set_block_mode(inp, 1);
}
else {
for( ; lenbytes; lenbytes-- ) {
pktlen <<= 8;
pktlen |= hdr[hdrlen++] = iobuf_get_noeof(inp);
}
}
}
if( out && pkttype ) {
if( iobuf_write( out, hdr, hdrlen ) == -1 )
rc = G10ERR_WRITE_FILE;
else
rc = copy_packet(inp, out, pkttype, pktlen );
goto leave;
}
if( do_skip || !pkttype || (reqtype && pkttype != reqtype) ) {
skip_rest(inp, pktlen);
*skip = 1;
rc = 0;
goto leave;
}
- if( DBG_PACKET )
+ if( DBG_PACKET ) {
+ #ifdef DEBUG_PARSE_PACKET
+ log_debug("parse_packet(iob=%d): type=%d length=%lu%s (%s.%s.%d)\n",
+ iobuf_id(inp), pkttype, pktlen, new_ctb?" (new_ctb)":"",
+ dbg_w, dbg_f, dbg_l );
+ #else
log_debug("parse_packet(iob=%d): type=%d length=%lu%s\n",
iobuf_id(inp), pkttype, pktlen, new_ctb?" (new_ctb)":"" );
+ #endif
+ }
pkt->pkttype = pkttype;
rc = G10ERR_UNKNOWN_PACKET; /* default error */
switch( pkttype ) {
case PKT_PUBLIC_KEY:
case PKT_PUBLIC_SUBKEY:
pkt->pkt.public_key = m_alloc_clear(sizeof *pkt->pkt.public_key );
rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt );
break;
case PKT_SECRET_KEY:
case PKT_SECRET_SUBKEY:
pkt->pkt.secret_key = m_alloc_clear(sizeof *pkt->pkt.secret_key );
rc = parse_key(inp, pkttype, pktlen, hdr, hdrlen, pkt );
break;
case PKT_SYMKEY_ENC:
rc = parse_symkeyenc( inp, pkttype, pktlen, pkt );
break;
case PKT_PUBKEY_ENC:
rc = parse_pubkeyenc(inp, pkttype, pktlen, pkt );
break;
case PKT_SIGNATURE:
pkt->pkt.signature = m_alloc_clear(sizeof *pkt->pkt.signature );
rc = parse_signature(inp, pkttype, pktlen, pkt->pkt.signature );
break;
case PKT_ONEPASS_SIG:
pkt->pkt.onepass_sig = m_alloc_clear(sizeof *pkt->pkt.onepass_sig );
rc = parse_onepass_sig(inp, pkttype, pktlen, pkt->pkt.onepass_sig );
break;
case PKT_USER_ID:
rc = parse_user_id(inp, pkttype, pktlen, pkt );
break;
case PKT_OLD_COMMENT:
case PKT_COMMENT:
rc = parse_comment(inp, pkttype, pktlen, pkt);
break;
case PKT_RING_TRUST:
parse_trust(inp, pkttype, pktlen);
rc = G10ERR_UNKNOWN_PACKET;
break;
case PKT_PLAINTEXT:
rc = parse_plaintext(inp, pkttype, pktlen, pkt, new_ctb );
break;
case PKT_COMPRESSED:
rc = parse_compressed(inp, pkttype, pktlen, pkt, new_ctb );
break;
case PKT_ENCRYPTED:
rc = parse_encrypted(inp, pkttype, pktlen, pkt, new_ctb );
break;
default:
skip_packet(inp, pkttype, pktlen);
break;
}
leave:
if( !rc && iobuf_error(inp) )
rc = G10ERR_INV_KEYRING;
return rc;
}
static void
dump_hex_line( int c, int *i )
{
if( *i && !(*i%8) ) {
if( *i && !(*i%24) )
printf("\n%4d:", *i );
else
putchar(' ');
}
if( c == -1 )
printf(" EOF" );
else
printf(" %02x", c );
++*i;
}
static int
copy_packet( IOBUF inp, IOBUF out, int pkttype, unsigned long pktlen )
{
int n;
char buf[100];
if( iobuf_in_block_mode(inp) ) {
while( (n = iobuf_read( inp, buf, 100 )) != -1 )
if( iobuf_write(out, buf, n ) )
return G10ERR_WRITE_FILE; /* write error */
}
else if( !pktlen && pkttype == PKT_COMPRESSED ) {
+ log_debug("copy_packet: compressed!\n");
/* compressed packet, copy till EOF */
while( (n = iobuf_read( inp, buf, 100 )) != -1 )
if( iobuf_write(out, buf, n ) )
return G10ERR_WRITE_FILE; /* write error */
}
else {
for( ; pktlen; pktlen -= n ) {
n = pktlen > 100 ? 100 : pktlen;
n = iobuf_read( inp, buf, n );
if( n == -1 )
return G10ERR_READ_FILE;
if( iobuf_write(out, buf, n ) )
return G10ERR_WRITE_FILE; /* write error */
}
}
return 0;
}
static void
skip_packet( IOBUF inp, int pkttype, unsigned long pktlen )
{
if( list_mode ) {
if( pkttype == PKT_MARKER )
fputs(":marker packet:\n", stdout );
else
printf(":unknown packet: type %2d, length %lu\n", pkttype, pktlen);
if( pkttype ) {
int c, i=0 ;
if( pkttype != PKT_MARKER )
fputs("dump:", stdout );
if( iobuf_in_block_mode(inp) ) {
while( (c=iobuf_get(inp)) != -1 )
dump_hex_line(c, &i);
}
else {
for( ; pktlen; pktlen-- )
dump_hex_line(iobuf_get(inp), &i);
}
putchar('\n');
return;
}
}
skip_rest(inp,pktlen);
}
static void
skip_rest( IOBUF inp, unsigned long pktlen )
{
if( iobuf_in_block_mode(inp) ) {
while( iobuf_get(inp) != -1 )
;
}
else {
for( ; pktlen; pktlen-- )
if( iobuf_get(inp) == -1 )
break;
}
}
static void *
read_rest( IOBUF inp, ulong *r_pktlen )
{
byte *p;
int i;
size_t pktlen = *r_pktlen;
if( iobuf_in_block_mode(inp) ) {
log_error("read_rest: can't store stream data\n");
p = NULL;
}
else {
p = m_alloc( pktlen + 2 );
p[0] = pktlen >> 8;
p[1] = pktlen & 0xff;
for(i=2; pktlen; pktlen--, i++ )
p[i] = iobuf_get(inp);
}
*r_pktlen = 0;
return p;
}
static void *
read_rest2( IOBUF inp, size_t pktlen )
{
byte *p;
int i;
if( iobuf_in_block_mode(inp) ) {
log_error("read_rest: can't store stream data\n");
p = NULL;
}
else {
p = m_alloc( pktlen );
for(i=0; pktlen; pktlen--, i++ )
p[i] = iobuf_get(inp);
}
return p;
}
static int
parse_symkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
{
PKT_symkey_enc *k;
int i, version, s2kmode, cipher_algo, hash_algo, seskeylen, minlen;
if( pktlen < 4 ) {
log_error("packet(%d) too short\n", pkttype);
goto leave;
}
version = iobuf_get_noeof(inp); pktlen--;
if( version != 4 ) {
log_error("packet(%d) with unknown version %d\n", pkttype, version);
goto leave;
}
if( pktlen > 200 ) { /* (we encode the seskeylen in a byte) */
log_error("packet(%d) too large\n", pkttype);
goto leave;
}
cipher_algo = iobuf_get_noeof(inp); pktlen--;
s2kmode = iobuf_get_noeof(inp); pktlen--;
hash_algo = iobuf_get_noeof(inp); pktlen--;
switch( s2kmode ) {
case 0: /* simple s2k */
minlen = 0;
break;
case 1: /* salted s2k */
minlen = 8;
break;
case 3: /* iterated+salted s2k */
minlen = 9;
break;
default:
log_error("unknown S2K %d\n", s2kmode );
goto leave;
}
if( minlen > pktlen ) {
log_error("packet with S2K %d too short\n", s2kmode );
goto leave;
}
seskeylen = pktlen - minlen;
k = packet->pkt.symkey_enc = m_alloc_clear( sizeof *packet->pkt.symkey_enc
+ seskeylen - 1 );
k->version = version;
k->cipher_algo = cipher_algo;
k->s2k.mode = s2kmode;
k->s2k.hash_algo = hash_algo;
if( s2kmode == 1 || s2kmode == 3 ) {
for(i=0; i < 8 && pktlen; i++, pktlen-- )
k->s2k.salt[i] = iobuf_get_noeof(inp);
}
if( s2kmode == 3 ) {
k->s2k.count = iobuf_get(inp); pktlen--;
}
k->seskeylen = seskeylen;
for(i=0; i < seskeylen && pktlen; i++, pktlen-- )
k->seskey[i] = iobuf_get_noeof(inp);
assert( !pktlen );
if( list_mode ) {
printf(":symkey enc packet: version %d, cipher %d, s2k %d, hash %d\n",
version, cipher_algo, s2kmode, hash_algo);
if( s2kmode == 1 || s2kmode == 3 ) {
printf("\tsalt ");
for(i=0; i < 8; i++ )
printf("%02x", k->s2k.salt[i]);
if( s2kmode == 3 )
printf(", count %lu\n", (ulong)k->s2k.count );
printf("\n");
}
}
leave:
skip_rest(inp, pktlen);
return 0;
}
static int
parse_pubkeyenc( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
{
unsigned n;
int i, ndata;
PKT_pubkey_enc *k;
k = packet->pkt.pubkey_enc = m_alloc(sizeof *packet->pkt.pubkey_enc );
if( pktlen < 12 ) {
log_error("packet(%d) too short\n", pkttype);
goto leave;
}
k->version = iobuf_get_noeof(inp); pktlen--;
if( k->version != 2 && k->version != 3 ) {
log_error("packet(%d) with unknown version %d\n", pkttype, k->version);
goto leave;
}
k->keyid[0] = read_32(inp); pktlen -= 4;
k->keyid[1] = read_32(inp); pktlen -= 4;
k->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
k->throw_keyid = 0; /* only used as flag for build_packet */
if( list_mode )
printf(":pubkey enc packet: version %d, algo %d, keyid %08lX%08lX\n",
k->version, k->pubkey_algo, (ulong)k->keyid[0], (ulong)k->keyid[1]);
ndata = pubkey_get_nenc(k->pubkey_algo);
if( !ndata ) {
if( list_mode )
printf("\tunsupported algorithm %d\n", k->pubkey_algo );
unknown_pubkey_warning( k->pubkey_algo );
k->data[0] = NULL; /* no need to store the encrypted data */
}
else {
for( i=0; i < ndata; i++ ) {
n = pktlen;
k->data[i] = mpi_read(inp, &n, 0); pktlen -=n;
if( list_mode ) {
printf("\tdata: ");
mpi_print(stdout, k->data[i], mpi_print_mode );
putchar('\n');
}
}
}
leave:
skip_rest(inp, pktlen);
return 0;
}
static void
dump_sig_subpkt( int hashed, int type, int critical,
const byte *buffer, size_t buflen, size_t length )
{
const char *p=NULL;
int i;
printf("\t%s%ssubpkt %d len %u (", /*)*/
critical ? "critical ":"",
hashed ? "hashed ":"", type, (unsigned)length );
buffer++;
length--;
if( length > buflen ) {
printf("too short: buffer is only %u)\n", (unsigned)buflen );
return;
}
switch( type ) {
case SIGSUBPKT_SIG_CREATED:
if( length >= 4 )
printf("sig created %s", strtimestamp( buffer_to_u32(buffer) ) );
break;
case SIGSUBPKT_SIG_EXPIRE:
if( length >= 4 )
printf("sig expires after %s",
strtimevalue( buffer_to_u32(buffer) ) );
break;
case SIGSUBPKT_EXPORTABLE:
if( length )
printf("%sexportable", *buffer? "":"not ");
break;
case SIGSUBPKT_TRUST:
p = "trust signature";
break;
case SIGSUBPKT_REGEXP:
p = "regular expression";
break;
case SIGSUBPKT_REVOCABLE:
p = "revocable";
break;
case SIGSUBPKT_KEY_EXPIRE:
if( length >= 4 )
printf("key expires after %s",
strtimevalue( buffer_to_u32(buffer) ) );
break;
case SIGSUBPKT_ARR:
p = "additional recipient request";
break;
case SIGSUBPKT_PREF_SYM:
fputs("pref-sym-algos:", stdout );
for( i=0; i < length; i++ )
printf(" %d", buffer[i] );
break;
case SIGSUBPKT_REV_KEY:
p = "revocation key";
break;
case SIGSUBPKT_ISSUER:
if( length >= 8 )
printf("issuer key ID %08lX%08lX",
(ulong)buffer_to_u32(buffer),
(ulong)buffer_to_u32(buffer+4) );
break;
case SIGSUBPKT_NOTATION:
p = "notation data";
break;
case SIGSUBPKT_PREF_HASH:
fputs("pref-hash-algos:", stdout );
for( i=0; i < length; i++ )
printf(" %d", buffer[i] );
break;
case SIGSUBPKT_PREF_COMPR:
fputs("pref-zip-algos:", stdout );
for( i=0; i < length; i++ )
printf(" %d", buffer[i] );
break;
case SIGSUBPKT_KS_FLAGS:
p = "key server preferences";
break;
case SIGSUBPKT_PREF_KS:
p = "preferred key server";
break;
case SIGSUBPKT_PRIMARY_UID:
p = "primary user id";
break;
case SIGSUBPKT_POLICY:
p = "policy URL";
break;
case SIGSUBPKT_KEY_FLAGS:
p = "key flags";
break;
case SIGSUBPKT_SIGNERS_UID:
p = "signer's user id";
break;
case SIGSUBPKT_PRIV_ADD_SIG:
p = "signs additional user id";
break;
default: p = "?"; break;
}
printf("%s)\n", p? p: "");
}
/****************
* Returns: >= 0 offset into buffer
* -1 unknown type
* -2 unsupported type
* -3 subpacket too short
*/
static int
parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
{
switch( type ) {
case SIGSUBPKT_SIG_CREATED:
case SIGSUBPKT_SIG_EXPIRE:
case SIGSUBPKT_KEY_EXPIRE:
if( n < 4 )
break;
return 0;
case SIGSUBPKT_EXPORTABLE:
if( !n )
break;
return 0;
case SIGSUBPKT_ISSUER:/* issuer key ID */
if( n < 8 )
break;
return 0;
case SIGSUBPKT_PREF_SYM:
case SIGSUBPKT_PREF_HASH:
case SIGSUBPKT_PREF_COMPR:
return 0;
case SIGSUBPKT_PRIV_ADD_SIG:
/* because we use private data, we check the GNUPG marker */
if( n < 24 )
break;
if( buffer[0] != 'G' || buffer[1] != 'P' || buffer[2] != 'G' )
return -2;
return 3;
default: return -1;
}
return -3;
}
const byte *
parse_sig_subpkt( const byte *buffer, sigsubpkttype_t reqtype, size_t *ret_n )
{
int buflen;
int type;
int critical;
int offset;
size_t n;
if( !buffer )
return NULL;
buflen = (*buffer << 8) | buffer[1];
buffer += 2;
while( buflen ) {
n = *buffer++; buflen--;
if( n == 255 ) {
if( buflen < 4 )
goto too_short;
n = (buffer[0] << 24) | (buffer[1] << 16)
| (buffer[2] << 8) | buffer[3];
buffer += 4;
buflen -= 4;
}
else if( n >= 192 ) {
if( buflen < 2 )
goto too_short;
n = (( n - 192 ) << 8) + *buffer + 192;
buflen--;
}
if( buflen < n )
goto too_short;
type = *buffer;
if( type & 0x80 ) {
type &= 0x7f;
critical = 1;
}
else
critical = 0;
if( reqtype == SIGSUBPKT_TEST_CRITICAL ) {
if( critical ) {
if( n-1 > buflen+1 )
goto too_short;
if( parse_one_sig_subpkt(buffer+1, n-1, type ) < 0 ) {
log_info(_("subpacket of type %d has critical bit set\n"),
type);
return NULL; /* this is an error */
}
}
}
else if( reqtype < 0 ) /* list packets */
dump_sig_subpkt( reqtype == SIGSUBPKT_LIST_HASHED,
type, critical, buffer, buflen, n );
else if( type == reqtype ) { /* found */
buffer++;
n--;
if( n > buflen )
goto too_short;
if( ret_n )
*ret_n = n;
offset = parse_one_sig_subpkt(buffer, n, type );
switch( offset ) {
case -3:
log_error("subpacket of type %d too short\n", type);
return NULL;
case -2:
return NULL;
case -1:
BUG(); /* not yet needed */
default:
break;
}
return buffer+offset;
}
buffer += n; buflen -=n;
}
if( reqtype == SIGSUBPKT_TEST_CRITICAL )
return buffer; /* as value true to indicate that there is no
/* critical bit we don't understand */
return NULL; /* end of packets; not found */
too_short:
log_error("buffer shorter than subpacket\n");
return NULL;
}
const byte *
parse_sig_subpkt2( PKT_signature *sig, sigsubpkttype_t reqtype, size_t *ret_n )
{
const byte *p;
p = parse_sig_subpkt( sig->hashed_data, reqtype, ret_n );
if( !p )
p = parse_sig_subpkt( sig->unhashed_data, reqtype, ret_n );
return p;
}
static int
parse_signature( IOBUF inp, int pkttype, unsigned long pktlen,
PKT_signature *sig )
{
int md5_len=0;
unsigned n;
int is_v4=0;
int rc=0;
int i, ndata;
if( pktlen < 16 ) {
log_error("packet(%d) too short\n", pkttype);
goto leave;
}
sig->version = iobuf_get_noeof(inp); pktlen--;
if( sig->version == 4 )
is_v4=1;
else if( sig->version != 2 && sig->version != 3 ) {
log_error("packet(%d) with unknown version %d\n", pkttype, sig->version);
goto leave;
}
if( !is_v4 ) {
md5_len = iobuf_get_noeof(inp); pktlen--;
}
sig->sig_class = iobuf_get_noeof(inp); pktlen--;
if( !is_v4 ) {
sig->timestamp = read_32(inp); pktlen -= 4;
sig->keyid[0] = read_32(inp); pktlen -= 4;
sig->keyid[1] = read_32(inp); pktlen -= 4;
}
sig->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
sig->digest_algo = iobuf_get_noeof(inp); pktlen--;
if( is_v4 ) { /* read subpackets */
n = read_16(inp); pktlen -= 2; /* length of hashed data */
if( n > 10000 ) {
log_error("signature packet: hashed data too long\n");
rc = G10ERR_INVALID_PACKET;
goto leave;
}
if( n ) {
sig->hashed_data = m_alloc( n + 2 );
sig->hashed_data[0] = n << 8;
sig->hashed_data[1] = n;
if( iobuf_read(inp, sig->hashed_data+2, n ) != n ) {
log_error("premature eof while reading hashed signature data\n");
rc = -1;
goto leave;
}
pktlen -= n;
}
n = read_16(inp); pktlen -= 2; /* length of unhashed data */
if( n > 10000 ) {
log_error("signature packet: unhashed data too long\n");
rc = G10ERR_INVALID_PACKET;
goto leave;
}
if( n ) {
sig->unhashed_data = m_alloc( n + 2 );
sig->unhashed_data[0] = n << 8;
sig->unhashed_data[1] = n;
if( iobuf_read(inp, sig->unhashed_data+2, n ) != n ) {
log_error("premature eof while reading unhashed signature data\n");
rc = -1;
goto leave;
}
pktlen -= n;
}
}
if( pktlen < 5 ) { /* sanity check */
log_error("packet(%d) too short\n", pkttype);
rc = G10ERR_INVALID_PACKET;
goto leave;
}
sig->digest_start[0] = iobuf_get_noeof(inp); pktlen--;
sig->digest_start[1] = iobuf_get_noeof(inp); pktlen--;
if( is_v4 ) { /*extract required information */
const byte *p;
/* set sig->flags.unknown_critical if there is a
* critical bit set for packets which we do not understand */
if( !parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_TEST_CRITICAL, NULL)
|| !parse_sig_subpkt( sig->unhashed_data, SIGSUBPKT_TEST_CRITICAL,
NULL) )
{
sig->flags.unknown_critical = 1;
}
p = parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_SIG_CREATED, NULL );
if( !p )
log_error("signature packet without timestamp\n");
else
sig->timestamp = buffer_to_u32(p);
p = parse_sig_subpkt2( sig, SIGSUBPKT_ISSUER, NULL );
if( !p )
log_error("signature packet without keyid\n");
else {
sig->keyid[0] = buffer_to_u32(p);
sig->keyid[1] = buffer_to_u32(p+4);
}
}
if( list_mode ) {
printf(":signature packet: algo %d, keyid %08lX%08lX\n"
"\tversion %d, created %lu, md5len %d, sigclass %02x\n"
"\tdigest algo %d, begin of digest %02x %02x\n",
sig->pubkey_algo,
(ulong)sig->keyid[0], (ulong)sig->keyid[1],
sig->version, (ulong)sig->timestamp, md5_len, sig->sig_class,
sig->digest_algo,
sig->digest_start[0], sig->digest_start[1] );
if( is_v4 ) {
parse_sig_subpkt( sig->hashed_data, SIGSUBPKT_LIST_HASHED, NULL );
parse_sig_subpkt( sig->unhashed_data,SIGSUBPKT_LIST_UNHASHED, NULL);
}
}
ndata = pubkey_get_nsig(sig->pubkey_algo);
if( !ndata ) {
if( list_mode )
printf("\tunknown algorithm %d\n", sig->pubkey_algo );
unknown_pubkey_warning( sig->pubkey_algo );
/* we store the plain material in data[0], so that we are able
* to write it back with build_packet() */
sig->data[0] = read_rest(inp, &pktlen );
}
else {
for( i=0; i < ndata; i++ ) {
n = pktlen;
sig->data[i] = mpi_read(inp, &n, 0 );
pktlen -=n;
if( list_mode ) {
printf("\tdata: ");
mpi_print(stdout, sig->data[i], mpi_print_mode );
putchar('\n');
}
}
}
leave:
skip_rest(inp, pktlen);
return rc;
}
static int
parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
PKT_onepass_sig *ops )
{
int version;
if( pktlen < 13 ) {
log_error("packet(%d) too short\n", pkttype);
goto leave;
}
version = iobuf_get_noeof(inp); pktlen--;
if( version != 3 ) {
log_error("onepass_sig with unknown version %d\n", version);
goto leave;
}
ops->sig_class = iobuf_get_noeof(inp); pktlen--;
ops->digest_algo = iobuf_get_noeof(inp); pktlen--;
ops->pubkey_algo = iobuf_get_noeof(inp); pktlen--;
ops->keyid[0] = read_32(inp); pktlen -= 4;
ops->keyid[1] = read_32(inp); pktlen -= 4;
ops->last = iobuf_get_noeof(inp); pktlen--;
if( list_mode )
printf(":onepass_sig packet: keyid %08lX%08lX\n"
"\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n",
(ulong)ops->keyid[0], (ulong)ops->keyid[1],
version, ops->sig_class,
ops->digest_algo, ops->pubkey_algo, ops->last );
leave:
skip_rest(inp, pktlen);
return 0;
}
static int
parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
byte *hdr, int hdrlen, PACKET *pkt )
{
int i, version, algorithm;
unsigned n;
unsigned long timestamp, expiredate;
int npkey, nskey;
int is_v4=0;
int rc=0;
version = iobuf_get_noeof(inp); pktlen--;
if( pkttype == PKT_PUBLIC_SUBKEY && version == '#' ) {
/* early versions of G10 use old PGP comments packets;
* luckily all those comments are started by a hash */
if( list_mode ) {
printf(":rfc1991 comment packet: \"" );
for( ; pktlen; pktlen-- ) {
int c;
c = iobuf_get_noeof(inp);
if( c >= ' ' && c <= 'z' )
putchar(c);
else
printf("\\x%02x", c );
}
printf("\"\n");
}
skip_rest(inp, pktlen);
return 0;
}
else if( version == 4 )
is_v4=1;
else if( version != 2 && version != 3 ) {
log_error("packet(%d) with unknown version %d\n", pkttype, version);
goto leave;
}
if( pktlen < 11 ) {
log_error("packet(%d) too short\n", pkttype);
goto leave;
}
timestamp = read_32(inp); pktlen -= 4;
if( is_v4 )
expiredate = 0; /* have to get it from the selfsignature */
else {
unsigned short ndays;
ndays = read_16(inp); pktlen -= 2;
if( ndays )
expiredate = timestamp + ndays * 86400L;
else
expiredate = 0;
}
algorithm = iobuf_get_noeof(inp); pktlen--;
if( list_mode )
printf(":%s key packet:\n"
"\tversion %d, algo %d, created %lu, expires %lu\n",
pkttype == PKT_PUBLIC_KEY? "public" :
pkttype == PKT_SECRET_KEY? "secret" :
pkttype == PKT_PUBLIC_SUBKEY? "public sub" :
pkttype == PKT_SECRET_SUBKEY? "secret sub" : "??",
version, algorithm, timestamp, expiredate );
if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) {
PKT_secret_key *sk = pkt->pkt.secret_key;
sk->timestamp = timestamp;
sk->expiredate = expiredate;
sk->hdrbytes = hdrlen;
sk->version = version;
sk->pubkey_algo = algorithm;
sk->pubkey_usage = 0; /* not yet used */
}
else {
PKT_public_key *pk = pkt->pkt.public_key;
pk->timestamp = timestamp;
pk->expiredate = expiredate;
pk->hdrbytes = hdrlen;
pk->version = version;
pk->pubkey_algo = algorithm;
pk->pubkey_usage = 0; /* not yet used */
pk->keyid[0] = 0;
pk->keyid[1] = 0;
}
nskey = pubkey_get_nskey( algorithm );
npkey = pubkey_get_npkey( algorithm );
if( !npkey ) {
if( list_mode )
printf("\tunknown algorithm %d\n", algorithm );
unknown_pubkey_warning( algorithm );
}
if( pkttype == PKT_SECRET_KEY || pkttype == PKT_SECRET_SUBKEY ) {
PKT_secret_key *sk = pkt->pkt.secret_key;
byte temp[8];
if( !npkey ) {
sk->skey[0] = read_rest( inp, &pktlen );
goto leave;
}
for(i=0; i < npkey; i++ ) {
n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) {
printf( "\tskey[%d]: ", i);
mpi_print(stdout, sk->skey[i], mpi_print_mode );
putchar('\n');
}
}
sk->protect.algo = iobuf_get_noeof(inp); pktlen--;
if( sk->protect.algo ) {
sk->is_protected = 1;
sk->protect.s2k.count = 0;
if( sk->protect.algo == 255 ) {
if( pktlen < 3 ) {
rc = G10ERR_INVALID_PACKET;
goto leave;
}
sk->protect.algo = iobuf_get_noeof(inp); pktlen--;
sk->protect.s2k.mode = iobuf_get_noeof(inp); pktlen--;
sk->protect.s2k.hash_algo = iobuf_get_noeof(inp); pktlen--;
switch( sk->protect.s2k.mode ) {
case 1:
case 3:
for(i=0; i < 8 && pktlen; i++, pktlen-- )
temp[i] = iobuf_get_noeof(inp);
memcpy(sk->protect.s2k.salt, temp, 8 );
break;
}
switch( sk->protect.s2k.mode ) {
case 0: if( list_mode ) printf( "\tsimple S2K" );
break;
case 1: if( list_mode ) printf( "\tsalted S2K" );
break;
case 3: if( list_mode ) printf( "\titer+salt S2K" );
break;
default:
if( list_mode )
printf( "\tunknown S2K %d\n",
sk->protect.s2k.mode );
rc = G10ERR_INVALID_PACKET;
goto leave;
}
if( list_mode ) {
printf(", algo: %d, hash: %d",
sk->protect.algo,
sk->protect.s2k.hash_algo );
if( sk->protect.s2k.mode == 1
|| sk->protect.s2k.mode == 3 ) {
printf(", salt: ");
for(i=0; i < 8; i++ )
printf("%02x", sk->protect.s2k.salt[i]);
}
putchar('\n');
}
if( sk->protect.s2k.mode == 3 ) {
if( pktlen < 1 ) {
rc = G10ERR_INVALID_PACKET;
goto leave;
}
sk->protect.s2k.count = iobuf_get(inp);
pktlen--;
if( list_mode )
printf("\tprotect count: %lu\n",
(ulong)sk->protect.s2k.count);
}
}
else { /* old version; no S2K, so we set mode to 0, hash MD5 */
sk->protect.s2k.mode = 0;
/* We need a kludge to cope with old GNUPG versions */
sk->protect.s2k.hash_algo =
( sk->protect.algo == CIPHER_ALGO_BLOWFISH160
&& algorithm == PUBKEY_ALGO_ELGAMAL_E ) ?
DIGEST_ALGO_RMD160 : DIGEST_ALGO_MD5;
if( list_mode )
printf( "\tprotect algo: %d (hash algo: %d)\n",
sk->protect.algo, sk->protect.s2k.hash_algo );
}
if( pktlen < 8 ) {
rc = G10ERR_INVALID_PACKET;
goto leave;
}
/* fixme: Add support for other blocksizes */
for(i=0; i < 8 && pktlen; i++, pktlen-- )
temp[i] = iobuf_get_noeof(inp);
if( list_mode ) {
printf( "\tprotect IV: ");
for(i=0; i < 8; i++ )
printf(" %02x", temp[i] );
putchar('\n');
}
memcpy(sk->protect.iv, temp, 8 );
}
else
sk->is_protected = 0;
/* It does not make sense to read it into secure memory.
* If the user is so careless, not to protect his secret key,
* we can assume, that he operates an open system :=(.
* So we put the key into secure memory when we unprotect it. */
if( is_v4 && sk->is_protected ){
/* ugly; the length is encrypted too, so we read all
* stuff up to the end of the packet into the first
* skey element */
sk->skey[npkey] = mpi_set_opaque(NULL,
read_rest2(inp, pktlen), pktlen );
pktlen = 0;
if( list_mode ) {
printf("\tencrypted stuff follows\n");
}
}
else { /* v3 method: the mpi length is not encrypted */
for(i=npkey; i < nskey; i++ ) {
n = pktlen; sk->skey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
if( sk->is_protected )
mpi_set_protect_flag(sk->skey[i]);
if( list_mode ) {
printf( "\tskey[%d]: ", i);
if( sk->is_protected )
printf( "[encrypted]\n");
else {
mpi_print(stdout, sk->skey[i], mpi_print_mode );
putchar('\n');
}
}
}
sk->csum = read_16(inp); pktlen -= 2;
if( list_mode ) {
printf("\tchecksum: %04hx\n", sk->csum);
}
}
}
else {
PKT_public_key *pk = pkt->pkt.public_key;
if( !npkey ) {
pk->pkey[0] = read_rest( inp, &pktlen );
goto leave;
}
for(i=0; i < npkey; i++ ) {
n = pktlen; pk->pkey[i] = mpi_read(inp, &n, 0 ); pktlen -=n;
if( list_mode ) {
printf( "\tpkey[%d]: ", i);
mpi_print(stdout, pk->pkey[i], mpi_print_mode );
putchar('\n');
}
}
}
leave:
skip_rest(inp, pktlen);
return rc;
}
static int
parse_user_id( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
{
byte *p;
packet->pkt.user_id = m_alloc(sizeof *packet->pkt.user_id + pktlen - 1);
packet->pkt.user_id->len = pktlen;
p = packet->pkt.user_id->name;
for( ; pktlen; pktlen--, p++ )
*p = iobuf_get_noeof(inp);
if( list_mode ) {
int n = packet->pkt.user_id->len;
printf(":user id packet: \"");
for(p=packet->pkt.user_id->name; n; p++, n-- ) {
if( *p >= ' ' && *p <= 'z' )
putchar(*p);
else
printf("\\x%02x", *p );
}
printf("\"\n");
}
return 0;
}
static int
parse_comment( IOBUF inp, int pkttype, unsigned long pktlen, PACKET *packet )
{
byte *p;
packet->pkt.comment = m_alloc(sizeof *packet->pkt.comment + pktlen - 1);
packet->pkt.comment->len = pktlen;
p = packet->pkt.comment->data;
for( ; pktlen; pktlen--, p++ )
*p = iobuf_get_noeof(inp);
if( list_mode ) {
int n = packet->pkt.comment->len;
printf(":%scomment packet: \"", pkttype == PKT_OLD_COMMENT?
"OpenPGP draft " : "" );
for(p=packet->pkt.comment->data; n; p++, n-- ) {
if( *p >= ' ' && *p <= 'z' )
putchar(*p);
else
printf("\\x%02x", *p );
}
printf("\"\n");
}
return 0;
}
static void
parse_trust( IOBUF inp, int pkttype, unsigned long pktlen )
{
int c;
c = iobuf_get_noeof(inp);
if( list_mode )
printf(":trust packet: flag=%02x\n", c );
}
static int
parse_plaintext( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *pkt, int new_ctb )
{
int mode, namelen;
PKT_plaintext *pt;
byte *p;
int c, i;
if( pktlen && pktlen < 6 ) {
log_error("packet(%d) too short (%lu)\n", pkttype, (ulong)pktlen);
goto leave;
}
mode = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
namelen = iobuf_get_noeof(inp); if( pktlen ) pktlen--;
pt = pkt->pkt.plaintext = m_alloc(sizeof *pkt->pkt.plaintext + namelen -1);
pt->new_ctb = new_ctb;
pt->mode = mode;
pt->namelen = namelen;
if( pktlen ) {
for( i=0; pktlen > 4 && i < namelen; pktlen--, i++ )
pt->name[i] = iobuf_get_noeof(inp);
}
else {
for( i=0; i < namelen; i++ )
if( (c=iobuf_get(inp)) == -1 )
break;
else
pt->name[i] = c;
}
pt->timestamp = read_32(inp); if( pktlen) pktlen -= 4;
pt->len = pktlen;
pt->buf = inp;
pktlen = 0;
if( list_mode ) {
printf(":literal data packet:\n"
"\tmode %c, created %lu, name=\"",
mode >= ' ' && mode <'z'? mode : '?',
(ulong)pt->timestamp );
for(p=pt->name,i=0; i < namelen; p++, i++ ) {
if( *p >= ' ' && *p <= 'z' )
putchar(*p);
else
printf("\\x%02x", *p );
}
printf("\",\n\traw data: %lu bytes\n", (ulong)pt->len );
}
leave:
return 0;
}
static int
parse_compressed( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *pkt, int new_ctb )
{
PKT_compressed *zd;
/* pktlen is here 0, but data follows
* (this should be the last object in a file or
* the compress algorithm should know the length)
*/
zd = pkt->pkt.compressed = m_alloc(sizeof *pkt->pkt.compressed );
zd->len = 0; /* not yet used */
zd->algorithm = iobuf_get_noeof(inp);
zd->new_ctb = new_ctb;
zd->buf = inp;
if( list_mode )
printf(":compressed packet: algo=%d\n", zd->algorithm);
return 0;
}
static int
parse_encrypted( IOBUF inp, int pkttype, unsigned long pktlen,
PACKET *pkt, int new_ctb )
{
PKT_encrypted *ed;
ed = pkt->pkt.encrypted = m_alloc(sizeof *pkt->pkt.encrypted );
ed->len = pktlen;
ed->buf = NULL;
ed->new_ctb = new_ctb;
if( pktlen && pktlen < 10 ) {
log_error("packet(%d) too short\n", pkttype);
skip_rest(inp, pktlen);
goto leave;
}
if( list_mode ) {
if( pktlen )
printf(":encrypted data packet:\n\tlength: %lu\n", pktlen-10);
else
printf(":encrypted data packet:\n\tlength: unknown\n");
}
ed->buf = inp;
pktlen = 0;
leave:
return 0;
}
diff --git a/g10/passphrase.c b/g10/passphrase.c
index 966338ff9..7f975b840 100644
--- a/g10/passphrase.c
+++ b/g10/passphrase.c
@@ -1,267 +1,267 @@
/* passphrase.c - Get a passphrase
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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>
#include <assert.h>
#include "util.h"
#include "memory.h"
#include "options.h"
#include "ttyio.h"
#include "cipher.h"
#include "keydb.h"
#include "main.h"
#include "i18n.h"
#include "status.h"
static char *fd_passwd = NULL;
static char *next_pw = NULL;
static char *last_pw = NULL;
static void hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create );
int
have_static_passphrase()
{
return !!fd_passwd;
}
/****************
* Set the passphrase to be used for the next query and only for the next
* one.
*/
void
set_next_passphrase( const char *s )
{
m_free(next_pw);
next_pw = NULL;
if( s ) {
next_pw = m_alloc_secure( strlen(s)+1 );
strcpy(next_pw, s );
}
}
/****************
* Get the last passphrase used in passphrase_to_dek.
* Note: This removes the passphrase from this modules and
* the caller must free the result. May return NULL:
*/
char *
get_last_passphrase()
{
char *p = last_pw;
last_pw = NULL;
return p;
}
void
read_passphrase_from_fd( int fd )
{
int i, len;
char *pw;
if( !opt.batch )
tty_printf("Reading passphrase from file descriptor %d ...", fd );
for( pw = NULL, i = len = 100; ; i++ ) {
if( i >= len-1 ) {
char *pw2 = pw;
len += 100;
pw = m_alloc_secure( len );
if( pw2 )
memcpy(pw, pw2, i );
else
i=0;
}
if( read( fd, pw+i, 1) != 1 || pw[i] == '\n' )
break;
}
pw[i] = 0;
if( !opt.batch )
tty_printf("\b\b\b \n" );
m_free( fd_passwd );
fd_passwd = pw;
}
/****************
* Get a passphrase for the secret key with KEYID, display TEXT
* if the user needs to enter the passphrase.
* mode 0 = standard, 2 = create new passphrase
* Returns: a DEK with a session key; caller must free
* or NULL if the passphrase was not correctly repeated.
* (only for mode 2)
* a dek->keylen of 0 means: no passphrase entered.
* (only for mode 2)
*/
DEK *
passphrase_to_dek( u32 *keyid, int cipher_algo, STRING2KEY *s2k, int mode )
{
char *pw = NULL;
DEK *dek;
STRING2KEY help_s2k;
if( !s2k ) {
s2k = &help_s2k;
s2k->mode = 0;
/* this should be MD5 if cipher is IDEA, but because we do
* not have IDEA, we use the default one, the user
* can select it from the commandline
*/
s2k->hash_algo = opt.def_digest_algo?opt.def_digest_algo
:DEFAULT_DIGEST_ALGO;
}
if( keyid && !opt.batch && !next_pw ) {
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
size_t n;
char *p;
tty_printf(_("\nYou need a passphrase to unlock the secret key for\n"
"user: \"") );
p = get_user_id( keyid, &n );
tty_print_string( p, n );
m_free(p);
tty_printf("\"\n");
if( !get_pubkey( pk, keyid ) ) {
const char *s = pubkey_algo_to_string( pk->pubkey_algo );
tty_printf( _("(%u-bit %s key, ID %08lX, created %s)\n"),
nbits_from_pk( pk ), s?s:"?", (ulong)keyid[1],
strtimestamp(pk->timestamp) );
}
tty_printf("\n");
free_public_key( pk );
}
else if( keyid && !next_pw ) {
char buf[20];
sprintf( buf, "%08lX%08lX", (ulong)keyid[0], (ulong)keyid[1] );
write_status_text( STATUS_NEED_PASSPHRASE, buf );
}
if( next_pw ) {
pw = next_pw;
next_pw = NULL;
}
else if( fd_passwd ) {
pw = m_alloc_secure( strlen(fd_passwd)+1 );
strcpy( pw, fd_passwd );
}
else if( opt.batch )
log_fatal("Can't query password in batchmode\n");
else {
pw = cpr_get_hidden("passphrase.enter", _("Enter passphrase: ") );
tty_kill_prompt();
if( mode == 2 && !cpr_enabled() ) {
char *pw2 = cpr_get_hidden("passphrase.repeat",
_("Repeat passphrase: ") );
tty_kill_prompt();
if( strcmp(pw, pw2) ) {
m_free(pw2);
m_free(pw);
return NULL;
}
m_free(pw2);
}
}
dek = m_alloc_secure( sizeof *dek );
dek->algo = cipher_algo;
if( !*pw && mode == 2 )
dek->keylen = 0;
else
hash_passphrase( dek, pw, s2k, mode==2 );
m_free(last_pw);
last_pw = pw;
return dek;
}
/****************
* Hash a passphrase using the supplied s2k. If create is true, create
* a new salt or what else must be filled into the s2k for a new key.
* always needs: dek->algo, s2k->mode, s2k->hash_algo.
*/
static void
hash_passphrase( DEK *dek, char *pw, STRING2KEY *s2k, int create )
{
MD_HANDLE md;
int pass, i;
int used = 0;
int pwlen = strlen(pw);
assert( s2k->hash_algo );
dek->keylen = cipher_get_keylen( dek->algo ) / 8;
if( !(dek->keylen > 0 && dek->keylen <= DIM(dek->key)) )
BUG();
md = md_open( s2k->hash_algo, 1);
for(pass=0; used < dek->keylen ; pass++ ) {
if( pass ) {
md_reset(md);
for(i=0; i < pass; i++ ) /* preset the hash context */
md_putc(md, 0 );
}
if( s2k->mode == 1 || s2k->mode == 3 ) {
int len2 = pwlen + 8;
ulong count = len2;
if( create && !pass ) {
randomize_buffer(s2k->salt, 8, 1);
if( s2k->mode == 3 )
s2k->count = 96; /* 65536 iterations */
}
if( s2k->mode == 3 ) {
count = (16ul + (s2k->count & 15)) << ((s2k->count >> 4) + 6);
if( count < len2 )
count = len2;
}
/* a little bit complicated because we need a ulong for count */
while( count > len2 ) { /* maybe iterated+salted */
md_write( md, s2k->salt, 8 );
md_write( md, pw, pwlen );
count -= len2;
}
if( count < 8 )
md_write( md, s2k->salt, count );
else {
md_write( md, s2k->salt, 8 );
count -= 8;
assert( count >= 0 );
md_write( md, pw, count );
}
}
else
md_write( md, pw, pwlen );
md_final( md );
i = md_digest_length( s2k->hash_algo );
if( i > dek->keylen - used )
i = dek->keylen - used;
memcpy( dek->key+used, md_read(md, s2k->hash_algo), i );
used += i;
}
md_close(md);
}
diff --git a/g10/pkclist.c b/g10/pkclist.c
index fb0a89e7a..86c239115 100644
--- a/g10/pkclist.c
+++ b/g10/pkclist.c
@@ -1,709 +1,719 @@
/* pkclist.c
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "options.h"
#include "packet.h"
#include "errors.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "trustdb.h"
#include "ttyio.h"
#include "status.h"
#include "i18n.h"
#define CONTROL_D ('D' - 'A' + 1)
static void
show_paths( ulong lid, int only_first )
{
void *context = NULL;
unsigned otrust, validity;
int last_level, level;
last_level = 0;
while( (level=enum_cert_paths( &context, &lid, &otrust, &validity)) != -1){
char *p;
int rc;
size_t n;
u32 keyid[2];
PKT_public_key *pk ;
if( level < last_level && only_first )
break;
last_level = level;
rc = keyid_from_lid( lid, keyid );
if( rc ) {
log_error("ooops: can't get keyid for lid %lu\n", lid);
return;
}
pk = m_alloc_clear( sizeof *pk );
rc = get_pubkey( pk, keyid );
if( rc ) {
log_error("key %08lX: public key not found: %s\n",
(ulong)keyid[1], g10_errstr(rc) );
return;
}
tty_printf("%*s%4u%c/%08lX.%lu %s \"",
level*2, "",
nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ),
(ulong)keyid[1], lid, datestr_from_pk( pk ) );
#if 0
c = trust_letter(otrust);
if( c )
putchar( c );
else
printf( "%02x", otrust );
putchar('/');
c = trust_letter(validity);
if( c )
putchar( c );
else
printf( "%02x", validity );
putchar(' ');
#endif
p = get_user_id( keyid, &n );
tty_print_string( p, n ),
m_free(p);
tty_printf("\"\n");
free_public_key( pk );
}
enum_cert_paths( &context, NULL, NULL, NULL ); /* release context */
tty_printf("\n");
}
/****************
* Returns true if an ownertrust has changed.
*/
int
edit_ownertrust( ulong lid, int mode )
{
char *p;
int rc;
size_t n;
u32 keyid[2];
PKT_public_key *pk ;
int changed=0;
int quit=0;
rc = keyid_from_lid( lid, keyid );
if( rc ) {
log_error("ooops: can't get keyid for lid %lu\n", lid);
return 0;
}
pk = m_alloc_clear( sizeof *pk );
rc = get_pubkey( pk, keyid );
if( rc ) {
log_error("key %08lX: public key not found: %s\n",
(ulong)keyid[1], g10_errstr(rc) );
return 0;
}
if( !mode ) {
tty_printf(_("No trust value assigned to %lu:\n"
"%4u%c/%08lX %s \""), lid,
nbits_from_pk( pk ), pubkey_letter( pk->pubkey_algo ),
(ulong)keyid[1], datestr_from_pk( pk ) );
p = get_user_id( keyid, &n );
tty_print_string( p, n ),
m_free(p);
tty_printf("\"\n\n");
}
tty_printf(_(
"Please decide how far you trust this user to correctly\n"
"verify other users' keys (by looking at passports,\n"
"checking fingerprints from different sources...)?\n\n"
" 1 = Don't know\n"
" 2 = I do NOT trust\n"
" 3 = I trust marginally\n"
" 4 = I trust fully\n"
" s = please show me more information\n") );
if( mode )
tty_printf(_(" m = back to the main menu\n"));
else
tty_printf(_(" q = quit\n"));
tty_printf("\n");
for(;;) {
/* a string with valid answers */
char *ans = _("sSmMqQ");
if( strlen(ans) != 6 )
BUG();
p = cpr_get("edit_ownertrust.value",_("Your decision? "));
trim_spaces(p);
cpr_kill_prompt();
if( *p && p[1] )
;
else if( !p[1] && (*p >= '1' && *p <= '4') ) {
unsigned trust;
switch( *p ) {
case '1': trust = TRUST_UNDEFINED; break;
case '2': trust = TRUST_NEVER ; break;
case '3': trust = TRUST_MARGINAL ; break;
case '4': trust = TRUST_FULLY ; break;
default: BUG();
}
if( !update_ownertrust( lid, trust ) )
changed++;
break;
}
else if( *p == ans[0] || *p == ans[1] ) {
tty_printf(_(
"Certificates leading to an ultimately trusted key:\n"));
show_paths( lid, 1 );
}
else if( mode && (*p == ans[2] || *p == ans[3] || *p == CONTROL_D ) ) {
break ; /* back to the menu */
}
else if( !mode && (*p == ans[4] || *p == ans[5] ) ) {
quit = 1;
break ; /* back to the menu */
}
m_free(p); p = NULL;
}
m_free(p);
m_free(pk);
return quit? -1 : changed;
}
/****************
* Try to add some more owner trusts (interactive)
+ * This function presents all the signator in a certificate
+ * chain who have no trust value assigned.
* Returns: -1 if no ownertrust were added.
*/
static int
add_ownertrust( PKT_public_key *pk, int *quit )
{
int rc;
void *context = NULL;
ulong lid;
unsigned otrust, validity;
int any=0, changed=0, any_undefined=0;
*quit = 0;
tty_printf(
_("Could not find a valid trust path to the key. Let's see whether we\n"
"can assign some missing owner trust values.\n\n"));
rc = query_trust_record( pk );
if( rc ) {
log_error("Ooops: not in trustdb\n");
return -1;
}
lid = pk->local_id;
while( enum_cert_paths( &context, &lid, &otrust, &validity ) != -1 ) {
if( lid == pk->local_id )
continue;
any=1;
- if( otrust == TRUST_UNDEFINED || otrust == TRUST_EXPIRED ||
- otrust == TRUST_UNKNOWN ) {
+ if( changed ) {
+ /* because enum_cert_paths() makes a snapshop of the
+ * trust paths, the otrust and validity are not anymore
+ * valid after changing an entry - we have to reread
+ * those values from then on
+ */
+ otrust = get_ownertrust( lid );
+ }
+ if( otrust == TRUST_UNDEFINED ) {
any_undefined=1;
- enum_cert_paths_print( &context, NULL, lid );
+ enum_cert_paths_print( &context, NULL, changed, lid );
+ tty_printf("\n");
rc = edit_ownertrust( lid, 0 );
if( rc == -1 ) {
*quit = 1;
break;
}
else if( rc > 0 )
changed = 1;
}
}
enum_cert_paths( &context, NULL, NULL, NULL ); /* release context */
if( !any )
tty_printf(_("No path leading to one of our keys found.\n\n") );
else if( !any_undefined )
tty_printf(_("No certificates with undefined trust found.\n\n") );
else if( !changed )
tty_printf(_("No trust values changed.\n\n") );
return any? 0:-1;
}
/****************
* Check whether we can trust this pk which has a trustlevel of TRUSTLEVEL
* Returns: true if we trust.
*/
static int
do_we_trust( PKT_public_key *pk, int trustlevel )
{
int rc;
if( (trustlevel & TRUST_FLAG_REVOKED) ) {
log_info(_("key %08lX: key has been revoked!\n"),
(ulong)keyid_from_pk( pk, NULL) );
if( opt.batch )
return 0;
if( !cpr_get_answer_is_yes("revoked_key.override",
_("Use this key anyway? ")) )
return 0;
}
switch( (trustlevel & TRUST_MASK) ) {
case TRUST_UNKNOWN: /* No pubkey in trustDB: Insert and check again */
rc = insert_trust_record( pk );
if( rc ) {
log_error("failed to insert it into the trustdb: %s\n",
g10_errstr(rc) );
return 0; /* no */
}
rc = check_trust( pk, &trustlevel );
if( rc )
log_fatal("trust check after insert failed: %s\n",
g10_errstr(rc) );
if( trustlevel == TRUST_UNKNOWN || trustlevel == TRUST_EXPIRED )
BUG();
return do_we_trust( pk, trustlevel );
case TRUST_EXPIRED:
log_info(_("%08lX: key has expired\n"),
(ulong)keyid_from_pk( pk, NULL) );
return 0; /* no */
case TRUST_UNDEFINED:
if( opt.batch || opt.answer_no )
log_info(_("%08lX: no info to calculate a trust probability\n"),
(ulong)keyid_from_pk( pk, NULL) );
else {
int quit;
rc = add_ownertrust( pk, &quit );
if( !rc && !quit ) {
rc = check_trust( pk, &trustlevel );
if( rc )
log_fatal("trust check after add_ownertrust failed: %s\n",
g10_errstr(rc) );
/* fixme: this is recursive; we should unroll it */
return do_we_trust( pk, trustlevel );
}
}
return 0;
case TRUST_NEVER:
log_info(_("%08lX: We do NOT trust this key\n"),
(ulong)keyid_from_pk( pk, NULL) );
return 0; /* no */
case TRUST_MARGINAL:
log_info(
_("%08lX: It is not sure that this key really belongs to the owner\n"
"but it is accepted anyway\n"), (ulong)keyid_from_pk( pk, NULL) );
return 1; /* yes */
case TRUST_FULLY:
if( opt.verbose )
log_info(_("This key probably belongs to the owner\n"));
return 1; /* yes */
case TRUST_ULTIMATE:
if( opt.verbose )
log_info(_("This key belongs to us\n"));
return 1; /* yes */
default: BUG();
}
/* Eventuell fragen falls der trustlevel nicht ausreichend ist */
return 1; /* yes */
}
/****************
* wrapper around do_we_trust, so we can ask whether to use the
* key anyway.
*/
static int
do_we_trust_pre( PKT_public_key *pk, int trustlevel )
{
int rc = do_we_trust( pk, trustlevel );
if( !opt.batch && !rc ) {
tty_printf(_(
"It is NOT certain that the key belongs to its owner.\n"
"If you *really* know what you are doing, you may answer\n"
"the next question with yes\n\n") );
if( cpr_get_answer_is_yes("untrusted_key.override",
_("Use this key anyway? ")) )
rc = 1;
}
else if( opt.always_trust && !rc ) {
log_info(_("WARNING: Using untrusted key!\n"));
rc = 1;
}
return rc;
}
/****************
* Check whether we can trust this signature.
* Returns: Error if we shall not trust this signatures.
*/
int
check_signatures_trust( PKT_signature *sig )
{
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
int trustlevel;
int dont_try = 0;
int rc=0;
rc = get_pubkey( pk, sig->keyid );
if( rc ) { /* this should not happen */
log_error("Ooops; the key vanished - can't check the trust\n");
rc = G10ERR_NO_PUBKEY;
goto leave;
}
retry:
rc = check_trust( pk, &trustlevel );
if( rc ) {
log_error("check trust failed: %s\n", g10_errstr(rc));
goto leave;
}
if( (trustlevel & TRUST_FLAG_REVOKED) ) {
write_status( STATUS_KEYREVOKED );
log_info(_("WARNING: This key has been revoked by its owner!\n"));
log_info(_(" This could mean that the signature is forgery.\n"));
}
switch( (trustlevel & TRUST_MASK) ) {
case TRUST_UNKNOWN: /* No pubkey in trustDB: Insert and check again */
rc = insert_trust_record( pk );
if( rc ) {
log_error("failed to insert it into the trustdb: %s\n",
g10_errstr(rc) );
goto leave;
}
rc = check_trust( pk, &trustlevel );
if( rc )
log_fatal("trust check after insert failed: %s\n",
g10_errstr(rc) );
if( trustlevel == TRUST_UNKNOWN || trustlevel == TRUST_EXPIRED )
BUG();
goto retry;
case TRUST_EXPIRED:
log_info(_("Note: This key has expired!\n"));
break;
case TRUST_UNDEFINED:
if( dont_try || opt.batch || opt.answer_no ) {
write_status( STATUS_TRUST_UNDEFINED );
log_info(_(
"WARNING: This key is not certified with a trusted signature!\n"));
log_info(_(
" There is no indication that the "
"signature belongs to the owner.\n" ));
}
else {
int quit;
rc = add_ownertrust( pk, &quit );
if( rc || quit ) {
dont_try = 1;
rc = 0;
}
goto retry;
}
break;
case TRUST_NEVER:
write_status( STATUS_TRUST_NEVER );
log_info(_("WARNING: We do NOT trust this key!\n"));
log_info(_(" The signature is probably a FORGERY.\n"));
rc = G10ERR_BAD_SIGN;
break;
case TRUST_MARGINAL:
write_status( STATUS_TRUST_MARGINAL );
log_info(_(
"WARNING: This key is not certified with sufficiently trusted signatures!\n"
));
log_info(_(
" It is not certain that the signature belongs to the owner.\n"
));
break;
case TRUST_FULLY:
write_status( STATUS_TRUST_FULLY );
break;
case TRUST_ULTIMATE:
write_status( STATUS_TRUST_ULTIMATE );
break;
default: BUG();
}
leave:
free_public_key( pk );
return rc;
}
void
release_pk_list( PK_LIST pk_list )
{
PK_LIST pk_rover;
for( ; pk_list; pk_list = pk_rover ) {
pk_rover = pk_list->next;
free_public_key( pk_list->pk );
m_free( pk_list );
}
}
int
build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned usage )
{
PK_LIST pk_list = NULL;
PKT_public_key *pk=NULL;
int rc=0;
if( !remusr && !opt.batch ) { /* ask */
char *answer=NULL;
tty_printf(_(
"You did not specify a user ID. (you may use \"-r\")\n\n"));
for(;;) {
rc = 0;
m_free(answer);
answer = cpr_get_utf8("pklist.user_id.enter",
_("Enter the user ID: "));
trim_spaces(answer);
cpr_kill_prompt();
if( !*answer )
break;
if( pk )
free_public_key( pk );
pk = m_alloc_clear( sizeof *pk );
pk->pubkey_usage = usage;
rc = get_pubkey_byname( NULL, pk, answer, NULL );
if( rc )
tty_printf(_("No such user ID.\n"));
else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, usage)) ) {
int trustlevel;
rc = check_trust( pk, &trustlevel );
if( rc ) {
log_error("error checking pk of '%s': %s\n",
answer, g10_errstr(rc) );
}
else if( do_we_trust_pre( pk, trustlevel ) ) {
PK_LIST r;
r = m_alloc( sizeof *r );
r->pk = pk; pk = NULL;
r->next = pk_list;
r->mark = 0;
pk_list = r;
break;
}
}
}
m_free(answer);
if( pk ) {
free_public_key( pk );
pk = NULL;
}
}
else {
for(; remusr; remusr = remusr->next ) {
pk = m_alloc_clear( sizeof *pk );
pk->pubkey_usage = usage;
if( (rc = get_pubkey_byname( NULL, pk, remusr->d, NULL )) ) {
free_public_key( pk ); pk = NULL;
log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) );
}
else if( !(rc=check_pubkey_algo2(pk->pubkey_algo, usage )) ) {
int trustlevel;
rc = check_trust( pk, &trustlevel );
if( rc ) {
free_public_key( pk ); pk = NULL;
log_error(_("%s: error checking key: %s\n"),
remusr->d, g10_errstr(rc) );
}
else if( do_we_trust_pre( pk, trustlevel ) ) {
/* note: do_we_trust may have changed the trustlevel */
PK_LIST r;
r = m_alloc( sizeof *r );
r->pk = pk; pk = NULL;
r->next = pk_list;
r->mark = 0;
pk_list = r;
}
else { /* we don't trust this pk */
free_public_key( pk ); pk = NULL;
}
}
else {
free_public_key( pk ); pk = NULL;
log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) );
}
}
}
if( !rc && !pk_list ) {
log_error(_("no valid addressees\n"));
rc = G10ERR_NO_USER_ID;
}
if( rc )
release_pk_list( pk_list );
else
*ret_pk_list = pk_list;
return rc;
}
/****************
* Return -1 if we could not find an algorithm.
*/
int
select_algo_from_prefs( PK_LIST pk_list, int preftype )
{
PK_LIST pkr;
u32 bits[8];
byte *pref = NULL;
size_t npref;
int i, j;
int compr_hack=0;
int any;
if( !pk_list )
return -1;
memset( bits, ~0, 8 * sizeof *bits );
for( pkr = pk_list; pkr; pkr = pkr->next ) {
u32 mask[8];
memset( mask, 0, 8 * sizeof *mask );
if( !pkr->pk->local_id )
BUG(); /* if this occurs, we can use get_ownertrust to set it */
if( preftype == PREFTYPE_SYM )
mask[0] |= (1<<2); /* 3DES is implicitly there */
m_free(pref);
pref = get_pref_data( pkr->pk->local_id, pkr->pk->namehash, &npref);
any = 0;
if( pref ) {
#if 0
log_hexdump("raw: ", pref, npref );
#endif
for(i=0; i+1 < npref; i+=2 ) {
if( pref[i] == preftype ) {
mask[pref[i+1]/32] |= 1 << (pref[i+1]%32);
any = 1;
}
}
}
if( (!pref || !any) && preftype == PREFTYPE_COMPR ) {
mask[0] |= 3; /* asume no_compression and old pgp */
compr_hack = 1;
}
#if 0
log_debug("mask=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n",
(ulong)mask[7], (ulong)mask[6], (ulong)mask[5], (ulong)mask[4],
(ulong)mask[3], (ulong)mask[2], (ulong)mask[1], (ulong)mask[0]);
#endif
for(i=0; i < 8; i++ )
bits[i] &= mask[i];
#if 0
log_debug("bits=%08lX%08lX%08lX%08lX%08lX%08lX%08lX%08lX\n",
(ulong)bits[7], (ulong)bits[6], (ulong)bits[5], (ulong)bits[4],
(ulong)bits[3], (ulong)bits[2], (ulong)bits[1], (ulong)bits[0]);
#endif
}
/* usable algorithms are now in bits
* We now use the last key from pk_list to select
* the algorithm we want to use. there are no
* preferences for the last key, we select the one
* corresponding to first set bit.
*/
i = -1;
any = 0;
if( pref ) {
for(j=0; j+1 < npref; j+=2 ) {
if( pref[j] == preftype ) {
any = 1;
if( (bits[pref[j+1]/32] & (1<<(pref[j+1]%32))) ) {
/* fixme: check whether this algoritm is available */
i = pref[j+1];
break;
}
}
}
}
if( !pref || !any ) {
for(j=0; j < 256; j++ )
if( (bits[j/32] & (1<<(j%32))) ) {
/* fixme: check whether this algoritm is available */
i = j;
break;
}
}
#if 0
log_debug("prefs of type %d: selected %d\n", preftype, i );
#endif
if( compr_hack && !i ) {
/* selected no compression, but we should check whether
* algorithm 1 is also available (the ordering is not relevant
* in this case). */
if( bits[0] & (1<<1) )
i = 1; /* yep; we can use compression algo 1 */
}
m_free(pref);
return i;
}
diff --git a/g10/plaintext.c b/g10/plaintext.c
index d471b9fe3..60f00cbf3 100644
--- a/g10/plaintext.c
+++ b/g10/plaintext.c
@@ -1,315 +1,315 @@
/* plaintext.c - process an plaintext packet
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "util.h"
#include "memory.h"
#include "options.h"
#include "packet.h"
#include "ttyio.h"
#include "filter.h"
#include "main.h"
#include "status.h"
#include "i18n.h"
/****************
* Defer the last CR,LF
*/
static void
special_md_putc( MD_HANDLE md, int c, int *state )
{
if( c == -1 ) { /* flush */
if( *state == 1 ) {
md_putc(md, '\r');
}
*state = 0;
return;
}
again:
switch( *state ) {
case 0:
if( c == '\r' )
*state = 1;
else
md_putc(md, c );
break;
case 1:
if( c == '\n' )
*state = 2;
else {
md_putc(md, '\r');
*state = 0;
goto again;
}
break;
case 2:
md_putc(md, '\r');
md_putc(md, '\n');
*state = 0;
goto again;
default: BUG();
}
}
/****************
* Handle a plaintext packet. If MFX is not NULL, update the MDs
* Note: we should use the filter stuff here, but we have to add some
* easy mimic to set a read limit, so we calculate only the
* bytes from the plaintext.
*/
int
handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
int nooutput, int clearsig )
{
char *fname = NULL;
FILE *fp = NULL;
int rc = 0;
int c;
int convert = pt->mode == 't';
int special_state = 0;
/* create the filename as C string */
if( nooutput )
;
else if( opt.outfile ) {
fname = m_alloc( strlen( opt.outfile ) + 1);
strcpy(fname, opt.outfile );
}
else if( pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8 ) ) {
log_info(_("data not saved; use option \"--output\" to save it\n"));
nooutput = 1;
}
else {
fname = m_alloc( pt->namelen +1 );
memcpy( fname, pt->name, pt->namelen );
fname[pt->namelen] = 0;
}
if( nooutput )
;
else if( !*fname || (*fname=='-' && !fname[1])) {
/* no filename or "-" given; write to stdout */
fp = stdout;
}
else if( !overwrite_filep( fname ) ) {
rc = G10ERR_CREATE_FILE;
goto leave;
}
if( fp || nooutput )
;
else if( !(fp = fopen(fname,"wb")) ) {
log_error("Error creating '%s': %s\n", fname, strerror(errno) );
rc = G10ERR_CREATE_FILE;
goto leave;
}
if( pt->len ) {
for( ; pt->len; pt->len-- ) {
if( (c = iobuf_get(pt->buf)) == -1 ) {
log_error("Problem reading source (%u bytes remaining)\n",
(unsigned)pt->len);
rc = G10ERR_READ_FILE;
goto leave;
}
if( mfx->md ) {
if( convert && clearsig )
special_md_putc(mfx->md, c, &special_state );
else
md_putc(mfx->md, c );
}
if( convert && !clearsig && c == '\r' )
continue; /* fixme: this hack might be too simple */
if( fp ) {
if( putc( c, fp ) == EOF ) {
log_error("Error writing to '%s': %s\n",
fname, strerror(errno) );
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
}
}
else {
while( (c = iobuf_get(pt->buf)) != -1 ) {
if( mfx->md ) {
if( convert && clearsig )
special_md_putc(mfx->md, c, &special_state );
else
md_putc(mfx->md, c );
}
if( convert && !clearsig && c == '\r' )
continue; /* fixme: this hack might be too simple */
if( fp ) {
if( putc( c, fp ) == EOF ) {
log_error("Error writing to '%s': %s\n",
fname, strerror(errno) );
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
}
iobuf_clear_eof(pt->buf);
}
if( mfx->md && convert && clearsig )
special_md_putc(mfx->md, -1, &special_state ); /* flush */
if( fp && fp != stdout && fclose(fp) ) {
log_error("Error closing '%s': %s\n", fname, strerror(errno) );
fp = NULL;
rc = G10ERR_WRITE_FILE;
goto leave;
}
fp = NULL;
leave:
if( fp && fp != stdout )
fclose(fp);
m_free(fname);
return rc;
}
/****************
* Ask for the detached datafile and calculate the digest from it.
* INFILE is the name of the input file.
*/
int
ask_for_detached_datafile( md_filter_context_t *mfx, const char *inname )
{
char *answer = NULL;
IOBUF fp;
int rc = 0;
int c;
fp = open_sigfile( inname ); /* open default file */
if( !fp && !opt.batch ) {
int any=0;
tty_printf("Detached signature.\n");
do {
m_free(answer);
answer = cpr_get("detached_signature.filename",
_("Please enter name of data file: "));
cpr_kill_prompt();
if( any && !*answer ) {
rc = G10ERR_READ_FILE;
goto leave;
}
fp = iobuf_open(answer);
if( !fp && errno == ENOENT ) {
tty_printf("No such file, try again or hit enter to quit.\n");
any++;
}
else if( !fp ) {
log_error("can't open '%s': %s\n", answer, strerror(errno) );
rc = G10ERR_READ_FILE;
goto leave;
}
} while( !fp );
}
if( !fp ) {
if( opt.verbose )
log_info(_("reading stdin ...\n"));
while( (c = getchar()) != EOF ) {
if( mfx->md )
md_putc(mfx->md, c );
}
}
else {
while( (c = iobuf_get(fp)) != -1 ) {
if( mfx->md )
md_putc(mfx->md, c );
}
iobuf_close(fp);
}
leave:
m_free(answer);
return rc;
}
static void
do_hash( MD_HANDLE md, IOBUF fp, int textmode )
{
text_filter_context_t tfx;
int c;
if( textmode ) {
memset( &tfx, 0, sizeof tfx);
iobuf_push_filter( fp, text_filter, &tfx );
}
while( (c = iobuf_get(fp)) != -1 )
md_putc(md, c );
}
/****************
* Hash the given files and append the hash to hash context md.
* If FILES is NULL, hash stdin.
*/
int
hash_datafiles( MD_HANDLE md, STRLIST files,
const char *sigfilename, int textmode )
{
IOBUF fp;
STRLIST sl=NULL;
if( !files ) {
/* check whether we can opne the signed material */
fp = open_sigfile( sigfilename );
if( fp ) {
do_hash( md, fp, textmode );
iobuf_close(fp);
return 0;
}
/* no we can't (no sigfile) - read signed stuff from stdin */
add_to_strlist( &sl, "-");
}
else
sl = files;
for( ; sl; sl = sl->next ) {
fp = iobuf_open( sl->d );
if( !fp ) {
log_error(_("can't open signed data '%s'\n"),
print_fname_stdin(sl->d));
if( !files )
free_strlist(sl);
return G10ERR_OPEN_FILE;
}
do_hash( md, fp, textmode );
iobuf_close(fp);
}
if( !files )
free_strlist(sl);
return 0;
}
diff --git a/g10/pref.c b/g10/pref.c
index 342696907..53ae41845 100644
--- a/g10/pref.c
+++ b/g10/pref.c
@@ -1,81 +1,81 @@
/* pref.c
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
*/
#define DEFINES_PREF_LIST 1
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include "errors.h"
#include "memory.h"
#include "util.h"
#include "ttyio.h"
#include "i18n.h"
#include "pref.h"
#define N_CIPHERS 3
#define N_DIGESTS 4
#define N_COMPRS 3
struct pref_list_s {
PREF_LIST *extend; /* if we need more, we link them together */
byte cipher[N_CIPHERS]; /* cipher algos */
byte digest[N_DIGESTS]; /* digest algos */
byte compr [N_COMPRS ]; /* compress algos (a 255 denotes no compression)*/
};
#if 0
PREF_LIST
new_pref_list()
{
return m_alloc_clear( sizeof(*PREF_LIST) );
}
void
release_pref_list( PREF_LIST pref )
{
while( pref ) {
PREF_LIST tmp = pref->extend;
m_free( pref );
pref = tmp;
}
}
PREF_LIST
copy_pref_list( PREF_LIST s )
{
PREF_LIST ss, ss, d = new_pref_list();
*d = *s;
for( ss = s->extend; ss; ss = ss->extend ) {
WORK WORK WORK
d->extend = new_pref_list();
*d->extend = *ss;
}
return d;
}
#endif
diff --git a/g10/pref.h b/g10/pref.h
index ec173c90b..cc827bbc5 100644
--- a/g10/pref.h
+++ b/g10/pref.h
@@ -1,42 +1,42 @@
/* pref.h
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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_PREF_H
#define G10_PREF_H 1
/* a structure to hold information abopu preferred algorithms */
typedef struct pref_list_s *PREF_LIST;
#ifndef DEFINES_PREF_LIST
struct pref_list_s { char preference_stuff[1]; };
#endif
PREF_LIST new_pref_list(void);
void release_pref_list( PREF_LIST pref );
#endif /*G10_PREF_H*/
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index cb021c47f..4e6e78409 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -1,195 +1,195 @@
/* pubkey-enc.c - public key encoded packet handling
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "packet.h"
#include "mpi.h"
#include "keydb.h"
#include "trustdb.h"
#include "cipher.h"
#include "status.h"
#include "i18n.h"
static int get_it( PKT_pubkey_enc *k,
DEK *dek, PKT_secret_key *sk, u32 *keyid );
/****************
* Get the session key from a pubkey enc paket and return
* it in DEK, which should have been allocated in secure memory.
*/
int
get_session_key( PKT_pubkey_enc *k, DEK *dek )
{
PKT_secret_key *sk = NULL;
int rc;
if( is_RSA(k->pubkey_algo) ) /* warn about that */
write_status(STATUS_RSA_OR_IDEA);
rc = check_pubkey_algo( k->pubkey_algo );
if( rc )
goto leave;
if( k->keyid[0] || k->keyid[1] ) {
sk = m_alloc_clear( sizeof *sk );
sk->pubkey_algo = k->pubkey_algo; /* we want a pubkey with this algo*/
if( !(rc = get_seckey( sk, k->keyid )) )
rc = get_it( k, dek, sk, k->keyid );
}
else { /* anonymous receiver: Try all available secret keys */
void *enum_context = NULL;
u32 keyid[2];
for(;;) {
if( sk )
free_secret_key( sk );
sk = m_alloc_clear( sizeof *sk );
rc=enum_secret_keys( &enum_context, sk, 1);
if( rc ) {
rc = G10ERR_NO_SECKEY;
break;
}
if( sk->pubkey_algo != k->pubkey_algo )
continue;
keyid_from_sk( sk, keyid );
log_info(_("anonymous receiver; trying secret key %08lX ...\n"),
(ulong)keyid[1] );
rc = check_secret_key( sk, 1 ); /* ask only once */
if( !rc )
rc = get_it( k, dek, sk, keyid );
if( !rc ) {
log_info(_("okay, we are the anonymous receiver.\n") );
break;
}
}
enum_secret_keys( &enum_context, NULL, 0 ); /* free context */
}
leave:
if( sk )
free_secret_key( sk );
return rc;
}
static int
get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
{
int rc;
MPI plain_dek = NULL;
byte *frame = NULL;
unsigned n, nframe;
u16 csum, csum2;
rc = pubkey_decrypt(sk->pubkey_algo, &plain_dek, k->data, sk->skey );
if( rc )
goto leave;
frame = mpi_get_buffer( plain_dek, &nframe, NULL );
mpi_free( plain_dek ); plain_dek = NULL;
/* Now get the DEK (data encryption key) from the frame
*
* Old versions encode the DEK in in this format (msb is left):
*
* 0 1 DEK(16 bytes) CSUM(2 bytes) 0 RND(n bytes) 2
*
* Later versions encode the DEK like this:
*
* 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
*
* (mpi_get_buffer already removed the leading zero).
*
* RND are non-zero randow bytes.
* A is the cipher algorithm
* DEK is the encryption key (session key) with length k
* CSUM
*/
if( DBG_CIPHER )
log_hexdump("DEK frame:", frame, nframe );
n=0;
if( n + 7 > nframe )
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
if( frame[n] == 1 && frame[nframe-1] == 2 ) {
log_info(_("old encoding of the DEK is not supported\n"));
rc = G10ERR_CIPHER_ALGO;
goto leave;
}
if( frame[n] != 2 ) /* somethink is wrong */
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */
;
n++; /* and the zero byte */
if( n + 4 > nframe )
{ rc = G10ERR_WRONG_SECKEY; goto leave; }
dek->keylen = nframe - (n+1) - 2;
dek->algo = frame[n++];
if( dek->algo == CIPHER_ALGO_IDEA )
write_status(STATUS_RSA_OR_IDEA);
rc = check_cipher_algo( dek->algo );
if( rc ) {
dek->algo = 0;
goto leave;
}
if( (dek->keylen*8) != cipher_get_keylen( dek->algo ) ) {
rc = G10ERR_WRONG_SECKEY;
goto leave;
}
/* copy the key to DEK and compare the checksum */
csum = frame[nframe-2] << 8;
csum |= frame[nframe-1];
memcpy( dek->key, frame+n, dek->keylen );
for( csum2=0, n=0; n < dek->keylen; n++ )
csum2 += dek->key[n];
if( csum != csum2 ) {
rc = G10ERR_WRONG_SECKEY;
goto leave;
}
if( DBG_CIPHER )
log_hexdump("DEK is:", dek->key, dek->keylen );
/* check that the algo is in the preferences */
{
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
if( (rc = get_pubkey( pk, keyid )) )
log_error("public key problem: %s\n", g10_errstr(rc) );
else if( !pk->local_id && query_trust_record(pk) )
log_error("can't check algorithm against preferences\n");
else if( dek->algo != CIPHER_ALGO_3DES
&& !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM, dek->algo ) )
log_info(_("NOTE: cipher algorithm %d not found in preferences\n"),
dek->algo );
free_public_key( pk );
rc = 0;
}
leave:
mpi_free(plain_dek);
m_free(frame);
return rc;
}
diff --git a/g10/revoke.c b/g10/revoke.c
index 2491ee023..b4728e27d 100644
--- a/g10/revoke.c
+++ b/g10/revoke.c
@@ -1,194 +1,194 @@
/* revoke.c
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "options.h"
#include "packet.h"
#include "errors.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "main.h"
#include "ttyio.h"
#include "status.h"
#include "i18n.h"
/****************
* Generate a revocation certificate for UNAME
*/
int
gen_revoke( const char *uname )
{
int rc = 0;
armor_filter_context_t afx;
compress_filter_context_t zfx;
PACKET pkt;
PKT_secret_key *sk; /* used as pointer into a kbnode */
PKT_public_key *pk = NULL;
PKT_signature *sig = NULL;
u32 sk_keyid[2];
IOBUF out = NULL;
KBNODE keyblock = NULL;
KBNODE node;
KBPOS kbpos;
if( opt.batch ) {
log_error(_("sorry, can't do this in batch mode\n"));
return G10ERR_GENERAL;
}
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx);
init_packet( &pkt );
/* search the userid */
rc = find_secret_keyblock_byname( &kbpos, uname );
if( rc ) {
log_error(_("secret key for user '%s' not found\n"), uname );
goto leave;
}
/* read the keyblock */
rc = read_keyblock( &kbpos, &keyblock );
if( rc ) {
log_error(_("error reading the certificate: %s\n"), g10_errstr(rc) );
goto leave;
}
/* get the keyid from the keyblock */
node = find_kbnode( keyblock, PKT_SECRET_KEY );
if( !node ) { /* maybe better to use log_bug ? */
log_error(_("Oops; secret key not found anymore!\n"));
rc = G10ERR_GENERAL;
goto leave;
}
/* fixme: should make a function out of this stuff,
* it's used all over the source */
sk = node->pkt->pkt.secret_key;
keyid_from_sk( sk, sk_keyid );
tty_printf("\nsec %4u%c/%08lX %s ",
nbits_from_sk( sk ),
pubkey_letter( sk->pubkey_algo ),
sk_keyid[1], datestr_from_sk(sk) );
{
size_t n;
char *p = get_user_id( sk_keyid, &n );
tty_print_string( p, n );
m_free(p);
tty_printf("\n");
}
pk = m_alloc_clear( sizeof *pk );
rc = get_pubkey( pk, sk_keyid );
if( rc ) {
log_error(_("no corresponding public key: %s\n"), g10_errstr(rc) );
goto leave;
}
if( cmp_public_secret_key( pk, sk ) ) {
log_error(_("public key does not match secret key!\n") );
rc = G10ERR_GENERAL;
goto leave;
}
tty_printf("\n");
if( !cpr_get_answer_is_yes("gen_revoke.okay",
_("Create a revocation certificate for this key? ")) ){
rc = 0;
goto leave;
}
switch( is_secret_key_protected( sk ) ) {
case -1:
log_error(_("unknown protection algorithm\n"));
rc = G10ERR_PUBKEY_ALGO;
break;
case 0:
tty_printf(_("NOTE: This key is not protected!\n"));
break;
default:
rc = check_secret_key( sk, 0 );
break;
}
if( rc )
goto leave;
if( !opt.armor )
tty_printf(_("ASCII armored output forced.\n"));
if( (rc = open_outfile( NULL, 0, &out )) )
goto leave;
afx.what = 1;
afx.hdrlines = "Comment: A revocation certificate should follow\n";
iobuf_push_filter( out, armor_filter, &afx );
if( opt.compress )
iobuf_push_filter( out, compress_filter, &zfx );
/* create it */
rc = make_keysig_packet( &sig, pk, NULL, NULL, sk, 0x20, 0, NULL, NULL);
if( rc ) {
log_error(_("make_keysig_packet failed: %s\n"), g10_errstr(rc));
goto leave;
}
init_packet( &pkt );
pkt.pkttype = PKT_SIGNATURE;
pkt.pkt.signature = sig;
rc = build_packet( out, &pkt );
if( rc ) {
log_error(_("build_packet failed: %s\n"), g10_errstr(rc) );
goto leave;
}
/* and issue a usage notice */
tty_printf(_("Revocation certificate created.\n\n"
"Please move it to a medium which you can hide away; if Mallory gets\n"
"access to this certificate he can use it to make your key unusable.\n"
"It is smart to print this certificate and store it away, just in case\n"
"your media become unreadable. But have some caution: The print system of\n"
"your machine might store the data and make it available to others!\n"));
leave:
if( pk )
free_public_key( pk );
if( sig )
free_seckey_enc( sig );
release_kbnode( keyblock );
if( rc )
iobuf_cancel(out);
else
iobuf_close(out);
return rc;
}
diff --git a/g10/ringedit.c b/g10/ringedit.c
index 008fa18c9..d46094cee 100644
--- a/g10/ringedit.c
+++ b/g10/ringedit.c
@@ -1,1760 +1,1780 @@
/* ringedit.c - Function for key ring editing
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 module supplies function for:
*
* - Search for a key block (pubkey and all other stuff) and return a
* handle for it.
*
* - Lock/Unlock a key block
*
* - Read a key block into a tree
*
* - Update a key block
*
* - Insert a new key block
*
* - Delete a key block
*
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h> /* for truncate */
#include <assert.h>
#ifdef HAVE_LIBGDBM
#include <gdbm.h>
#endif
#include "util.h"
#include "packet.h"
#include "memory.h"
#include "mpi.h"
#include "iobuf.h"
#include "keydb.h"
#include "host2net.h"
#include "options.h"
#include "main.h"
#include "i18n.h"
struct resource_table_struct {
int used;
int secret; /* this is a secret keyring */
char *fname;
IOBUF iobuf;
#ifdef HAVE_LIBGDBM
GDBM_FILE dbf;
#endif
enum resource_type rt;
};
typedef struct resource_table_struct RESTBL;
#define MAX_RESOURCES 10
static RESTBL resource_table[MAX_RESOURCES];
static const char *keyring_lock;
static int search( PACKET *pkt, KBPOS *kbpos, int secret );
static int keyring_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf,
const char *fname );
static int keyring_read( KBPOS *kbpos, KBNODE *ret_root );
static int keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs );
static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root );
#ifdef HAVE_LIBGDBM
static int do_gdbm_store( KBPOS *kbpos, KBNODE root, int update );
static int do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos,
const byte *fpr, int fprlen );
static int do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid );
static int do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root );
static int do_gdbm_enum( KBPOS *kbpos, KBNODE *ret_root );
#endif
static RESTBL *
check_pos( KBPOS *kbpos )
{
if( kbpos->resno < 0 || kbpos->resno >= MAX_RESOURCES )
return NULL;
if( !resource_table[kbpos->resno].used )
return NULL;
return resource_table + kbpos->resno;
}
#ifdef HAVE_LIBGDBM
static void
fatal_gdbm_error( const char *string )
{
log_fatal("gdbm failed: %s\n", string);
}
#endif /* HAVE_LIBGDBM */
static void
cleanup( void )
{
if( keyring_lock ) {
release_dotlock( keyring_lock );
keyring_lock = NULL;
}
}
/****************************************************************
****************** public functions ****************************
****************************************************************/
/****************
* Get the name of the keyrings, start with a sequence number pointing to a 0.
*/
const char *
enum_keyblock_resources( int *sequence, int secret )
{
int i = *sequence;
const char *name = NULL;
for(; i < MAX_RESOURCES; i++ )
if( resource_table[i].used && !resource_table[i].secret == !secret ) {
if( resource_table[i].fname ) {
name = resource_table[i].fname;
break;
}
}
*sequence = ++i;
return name;
}
/****************
* Register a resource (which currently may only be a keyring file).
* The first keyring which is added by this function is
* created if it does not exist.
* Note: this function may be called before secure memory is
* available.
*/
int
add_keyblock_resource( const char *url, int force, int secret )
{
static int initialized = 0;
static int any_secret, any_public;
const char *resname = url;
IOBUF iobuf = NULL;
int i;
char *filename = NULL;
int rc = 0;
enum resource_type rt = rt_UNKNOWN;
if( !initialized ) {
initialized = 1;
atexit( cleanup );
}
/* Do we have an URL?
* gnupg-gdbm:filename := this is a GDBM resource
* gnupg-ring:filename := this is a plain keyring
* filename := See what is is, but create as plain keyring.
*/
if( strlen( resname ) > 11 ) {
if( !strncmp( resname, "gnupg-ring:", 11 ) ) {
rt = rt_RING;
resname += 11;
}
else if( !strncmp( resname, "gnupg-gdbm:", 11 ) ) {
rt = rt_GDBM;
resname += 11;
}
#ifndef __MINGW32__
else if( strchr( resname, ':' ) ) {
log_error("%s: invalid URL\n", url );
rc = G10ERR_GENERAL;
goto leave;
}
#endif
}
if( *resname != '/' ) { /* do tilde expansion etc */
if( strchr(resname, '/') )
filename = make_filename(resname, NULL);
else
filename = make_filename(opt.homedir, resname, NULL);
}
else
filename = m_strdup( resname );
if( !force )
force = secret? !any_secret : !any_public;
for(i=0; i < MAX_RESOURCES; i++ )
if( !resource_table[i].used )
break;
if( i == MAX_RESOURCES ) {
rc = G10ERR_RESOURCE_LIMIT;
goto leave;
}
/* see whether we can determine the filetype */
if( rt == rt_UNKNOWN ) {
FILE *fp = fopen( filename, "rb" );
if( fp ) {
u32 magic;
if( fread( &magic, 4, 1, fp) == 1 ) {
if( magic == 0x13579ace )
rt = rt_GDBM;
else if( magic == 0xce9a5713 )
log_error("%s: endianess does not match\n", url );
else
rt = rt_RING;
}
else /* maybe empty: assume ring */
rt = rt_RING;
fclose( fp );
}
else /* no file yet: create ring */
rt = rt_RING;
}
switch( rt ) {
case rt_UNKNOWN:
log_error("%s: unknown resource type\n", url );
rc = G10ERR_GENERAL;
goto leave;
case rt_RING:
iobuf = iobuf_open( filename );
if( !iobuf && !force ) {
rc = G10ERR_OPEN_FILE;
goto leave;
}
if( !iobuf ) {
char *last_slash_in_filename;
last_slash_in_filename = strrchr(filename, '/');
*last_slash_in_filename = 0;
if( access(filename, F_OK) ) {
if( strlen(filename) >= 7
&& !strcmp(filename+strlen(filename)-7, "/.gnupg") ) {
#if __MINGW32__
if( mkdir(filename) )
#else
if( mkdir(filename, S_IRUSR|S_IWUSR|S_IXUSR) )
#endif
{
log_error( _("%s: can't create directory: %s\n"),
filename, strerror(errno));
rc = G10ERR_OPEN_FILE;
goto leave;
}
else
log_info( _("%s: directory created\n"), filename );
copy_options_file( filename );
}
else
{
rc = G10ERR_OPEN_FILE;
goto leave;
}
}
*last_slash_in_filename = '/';
iobuf = iobuf_create( filename );
if( !iobuf ) {
log_error(_("%s: can't create keyring: %s\n"),
filename, strerror(errno));
rc = G10ERR_OPEN_FILE;
goto leave;
}
else
log_info(_("%s: keyring created\n"), filename );
}
- #ifdef __MINGW32__
+ #if __MINGW32__ || 1
/* must close it again */
iobuf_close( iobuf );
iobuf = NULL;
#endif
break;
#ifdef HAVE_LIBGDBM
case rt_GDBM:
resource_table[i].dbf = gdbm_open( filename, 0,
force? GDBM_WRCREAT : GDBM_WRITER,
S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP | S_IROTH,
fatal_gdbm_error );
if( !resource_table[i].dbf ) {
log_error("%s: can't open gdbm file: %s\n",
filename, gdbm_strerror(gdbm_errno));
rc = G10ERR_OPEN_FILE;
goto leave;
}
break;
#endif
default:
log_error("%s: unsupported resource type\n", url );
rc = G10ERR_GENERAL;
goto leave;
}
resource_table[i].used = 1;
resource_table[i].secret = !!secret;
resource_table[i].fname = m_strdup(filename);
resource_table[i].iobuf = iobuf;
resource_table[i].rt = rt;
leave:
if( rc )
log_error("keyblock resource '%s': %s\n", filename, g10_errstr(rc) );
else if( secret )
any_secret = 1;
else
any_public = 1;
m_free( filename );
return rc;
}
/****************
* Return the resource name of the keyblock associated with KBPOS.
*/
const char *
keyblock_resource_name( KBPOS *kbpos )
{
RESTBL *rentry;
if( !(rentry = check_pos( kbpos )) || !rentry->fname )
log_bug("no name for keyblock resource %d\n", kbpos->resno );
return rentry->fname;
}
/****************
* Get a keyblock handle KBPOS from a filename. This can be used
* to get a handle for insert_keyblock for a new keyblock.
* Using a filename of NULL returns the default resource
*/
int
get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos )
{
int i;
for(i=0; i < MAX_RESOURCES; i++ )
if( resource_table[i].used && !resource_table[i].secret == !secret ) {
/* fixme: dos needs case insensitive file compare */
if( !filename || !strcmp( resource_table[i].fname, filename ) ) {
memset( kbpos, 0, sizeof *kbpos );
kbpos->resno = i;
kbpos->rt = resource_table[i].rt;
return 0;
}
}
return -1; /* not found */
}
/****************
* Search a keyblock which starts with the given packet and puts all
* information into KBPOS, which can be used later to access this key block.
* This function looks into all registered keyblock sources.
* PACKET must be a packet with either a secret_key or a public_key
*
* This function is intended to check whether a given certificate
* is already in a keyring or to prepare it for editing.
*
* Returns: 0 if found, -1 if not found or an errorcode.
*/
static int
search( PACKET *pkt, KBPOS *kbpos, int secret )
{
int i, rc, last_rc=-1;
for(i=0; i < MAX_RESOURCES; i++ ) {
if( resource_table[i].used && !resource_table[i].secret == !secret ) {
switch( resource_table[i].rt ) {
case rt_RING:
rc = keyring_search( pkt, kbpos, resource_table[i].iobuf,
resource_table[i].fname );
break;
#ifdef HAVE_LIBGDBM
case rt_GDBM: {
PKT_public_key *req_pk = pkt->pkt.public_key;
byte fpr[20];
size_t fprlen;
fingerprint_from_pk( req_pk, fpr, &fprlen );
rc = do_gdbm_locate( resource_table[i].dbf,
kbpos, fpr, fprlen );
}
break;
#endif
default: BUG();
}
kbpos->rt = resource_table[i].rt;
if( !rc ) {
kbpos->resno = i;
kbpos->fp = NULL;
return 0;
}
if( rc != -1 ) {
log_error("error searching resource %d: %s\n",
i, g10_errstr(rc));
last_rc = rc;
}
}
}
return last_rc;
}
/****************
* Combined function to search for a username and get the position
* of the keyblock.
*/
int
find_keyblock_byname( KBPOS *kbpos, const char *username )
{
PACKET pkt;
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
int rc;
rc = get_pubkey_byname( NULL, pk, username, NULL );
if( rc ) {
free_public_key(pk);
return rc;
}
init_packet( &pkt );
pkt.pkttype = PKT_PUBLIC_KEY;
pkt.pkt.public_key = pk;
rc = search( &pkt, kbpos, 0 );
free_public_key(pk);
return rc;
}
/****************
* Combined function to search for a key and get the position
* of the keyblock.
*/
int
find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk )
{
PACKET pkt;
int rc;
init_packet( &pkt );
pkt.pkttype = PKT_PUBLIC_KEY;
pkt.pkt.public_key = pk;
rc = search( &pkt, kbpos, 0 );
return rc;
}
/****************
* Combined function to search for a username and get the position
* of the keyblock. This function does not unprotect the secret key.
*/
int
find_secret_keyblock_byname( KBPOS *kbpos, const char *username )
{
PACKET pkt;
PKT_secret_key *sk = m_alloc_clear( sizeof *sk );
int rc;
rc = get_seckey_byname( sk, username, 0 );
if( rc ) {
free_secret_key(sk);
return rc;
}
init_packet( &pkt );
pkt.pkttype = PKT_SECRET_KEY;
pkt.pkt.secret_key = sk;
rc = search( &pkt, kbpos, 1 );
free_secret_key(sk);
return rc;
}
/****************
* Locate a keyblock in a database which is capable of direct access
* Put all information into KBPOS, which can be later be to access this
* key block.
* This function looks into all registered keyblock sources.
*
* Returns: 0 if found,
* -1 if not found
* G10ERR_UNSUPPORTED if no resource is able to handle this
* or another errorcode.
*/
int
locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr, int fprlen, int secret )
{
RESTBL *rentry;
int i, rc, any=0, last_rc=-1;
for(i=0, rentry = resource_table; i < MAX_RESOURCES; i++, rentry++ ) {
if( rentry->used && !rentry->secret == !secret ) {
kbpos->rt = rentry->rt;
switch( rentry->rt ) {
#ifdef HAVE_LIBGDBM
case rt_GDBM:
any = 1;
rc = do_gdbm_locate( rentry->dbf, kbpos, fpr, fprlen );
break;
#endif
default:
rc = G10ERR_UNSUPPORTED;
break;
}
if( !rc ) {
kbpos->resno = i;
kbpos->fp = NULL;
return 0;
}
else if( rc != -1 && rc != G10ERR_UNSUPPORTED ) {
log_error("error searching resource %d: %s\n",
i, g10_errstr(rc));
last_rc = rc;
}
}
}
return (last_rc == -1 && !any)? G10ERR_UNSUPPORTED : last_rc;
}
int
locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid, int shortkid, int secret )
{
RESTBL *rentry;
int i, rc, any=0, last_rc=-1;
if( shortkid )
return G10ERR_UNSUPPORTED;
for(i=0, rentry = resource_table; i < MAX_RESOURCES; i++, rentry++ ) {
if( rentry->used && !rentry->secret == !secret ) {
kbpos->rt = rentry->rt;
switch( rentry->rt ) {
#ifdef HAVE_LIBGDBM
case rt_GDBM:
any = 1;
rc = do_gdbm_locate_by_keyid( rentry->dbf, kbpos, keyid );
break;
#endif
default:
rc = G10ERR_UNSUPPORTED;
break;
}
if( !rc ) {
kbpos->resno = i;
kbpos->fp = NULL;
return 0;
}
else if( rc != -1 && rc != G10ERR_UNSUPPORTED ) {
log_error("error searching resource %d: %s\n",
i, g10_errstr(rc));
last_rc = rc;
}
}
}
return (last_rc == -1 && !any)? G10ERR_UNSUPPORTED : last_rc;
}
/****************
* Lock the keyblock; wait until it's available
* This function may change the internal data in kbpos, in cases
* when the keyblock to be locked has been modified.
* fixme: remove this function and add an option to search()?
*/
int
lock_keyblock( KBPOS *kbpos )
{
if( !check_pos(kbpos) )
return G10ERR_GENERAL;
return 0;
}
/****************
* Release a lock on a keyblock
*/
void
unlock_keyblock( KBPOS *kbpos )
{
if( !check_pos(kbpos) )
BUG();
}
/****************
* Read a complete keyblock and return the root in ret_root.
*/
int
read_keyblock( KBPOS *kbpos, KBNODE *ret_root )
{
if( !check_pos(kbpos) )
return G10ERR_GENERAL;
switch( kbpos->rt ) {
case rt_RING:
return keyring_read( kbpos, ret_root );
#ifdef HAVE_LIBGDBM
case rt_GDBM:
return do_gdbm_read( kbpos, ret_root );
#endif
default: BUG();
}
}
/****************
* This functions can be used to read through a complete keyring.
* Mode is: 0 = open
* 1 = read
* 2 = close
* 5 = open secret keyrings
* 11 = read but skip signature and comment packets.
* all others are reserved!
* Note that you do not need a search prior to this function,
* only a handle is needed.
* NOTE: It is not allowed to do an insert/update/delete with this
* keyblock, if you want to do this, use search/read!
*/
int
enum_keyblocks( int mode, KBPOS *kbpos, KBNODE *ret_root )
{
int rc = 0;
RESTBL *rentry;
if( !mode || mode == 5 || mode == 100 ) {
int i;
kbpos->fp = NULL;
if( !mode ) {
kbpos->secret = 0;
i = 0;
}
else if( mode == 5 ) {
kbpos->secret = 1;
mode = 0;
i = 0;
}
else
i = kbpos->resno+1;
for(; i < MAX_RESOURCES; i++ )
if( resource_table[i].used
&& !resource_table[i].secret == !kbpos->secret )
break;
if( i == MAX_RESOURCES )
return -1; /* no resources */
kbpos->resno = i;
rentry = check_pos( kbpos );
kbpos->rt = resource_table[i].rt;
+ kbpos->valid = 0;
switch( kbpos->rt ) {
case rt_RING:
kbpos->fp = iobuf_open( rentry->fname );
if( !kbpos->fp ) {
log_error("can't open '%s'\n", rentry->fname );
return G10ERR_OPEN_FILE;
}
break;
#ifdef HAVE_LIBGDBM
case rt_GDBM:
/* FIXME: make sure that there is only one enum at a time */
kbpos->offset = 0;
break;
#endif
default: BUG();
}
kbpos->pkt = NULL;
}
else if( mode == 1 || mode == 11 ) {
int cont;
do {
cont = 0;
switch( kbpos->rt ) {
case rt_RING:
if( !kbpos->fp )
return G10ERR_GENERAL;
rc = keyring_enum( kbpos, ret_root, mode == 11 );
break;
#ifdef HAVE_LIBGDBM
case rt_GDBM:
rc = do_gdbm_enum( kbpos, ret_root );
break;
#endif
default: BUG();
}
if( rc == -1 ) {
assert( !kbpos->pkt );
rentry = check_pos( kbpos );
assert(rentry);
/* close */
enum_keyblocks(2, kbpos, ret_root );
/* and open the next one */
rc = enum_keyblocks(100, kbpos, ret_root );
if( !rc )
cont = 1;
}
} while(cont);
}
else {
switch( kbpos->rt ) {
case rt_RING:
if( kbpos->fp ) {
iobuf_close( kbpos->fp );
kbpos->fp = NULL;
}
break;
case rt_GDBM:
break;
default:
log_error("OOPS in close enum_keyblocks - ignored\n");
return rc;
break;
}
/* release pending packet */
free_packet( kbpos->pkt );
m_free( kbpos->pkt );
}
return rc;
}
/****************
* Insert the keyblock described by ROOT into the keyring described
* by KBPOS. This actually appends the data to the keyfile.
*/
int
insert_keyblock( KBPOS *kbpos, KBNODE root )
{
int rc;
if( !check_pos(kbpos) )
return G10ERR_GENERAL;
switch( kbpos->rt ) {
case rt_RING:
rc = keyring_copy( kbpos, 1, root );
break;
#ifdef HAVE_LIBGDBM
case rt_GDBM:
rc = do_gdbm_store( kbpos, root, 0 );
break;
#endif
default: BUG();
}
return rc;
}
/****************
* Delete the keyblock described by KBPOS.
* The current code simply changes the keyblock in the keyring
* to packet of type 0 with the correct length. To help detect errors,
* zero bytes are written.
*/
int
delete_keyblock( KBPOS *kbpos )
{
int rc;
if( !check_pos(kbpos) )
return G10ERR_GENERAL;
switch( kbpos->rt ) {
case rt_RING:
rc = keyring_copy( kbpos, 2, NULL );
break;
#ifdef HAVE_LIBGDBM
case rt_GDBM:
log_debug("deleting gdbm keyblock is not yet implemented\n");
rc = 0;
break;
#endif
default: BUG();
}
return rc;
}
/****************
* Update the keyblock at KBPOS with the one in ROOT.
*/
int
update_keyblock( KBPOS *kbpos, KBNODE root )
{
int rc;
if( !check_pos(kbpos) )
return G10ERR_GENERAL;
switch( kbpos->rt ) {
case rt_RING:
rc = keyring_copy( kbpos, 3, root );
break;
#ifdef HAVE_LIBGDBM
case rt_GDBM:
rc = do_gdbm_store( kbpos, root, 1 );
break;
#endif
default: BUG();
}
return rc;
}
/****************************************************************
********** Implemenation of a user ID database **************
****************************************************************/
#if 0
/****************
* Layout of the user ID db
*
* This user ID DB provides fast lookup of user ID, but the user ids are
* not in any specific order.
*
* A string "GnuPG user db", a \n.
* user ids of one key, delimited by \t,
* a # or ^ followed by a 20 byte fingerprint, followed by an \n
- * The literal characters =, \n, \t, #, ^ must be replaced by a equal sign
+ * The literal characters %, \n, \t, #, ^ must be replaced by a percent sign
* and their hex value.
*
* (We use Boyer/Moore pattern matching)
*/
/****************
* This compiles pattern to the distance table, the table will be allocate
* here and must be freed by using free().
* Returns: Ptr to new allocated Table
* Caller must free the table.
*/
static size_t *
compile_bm_table( const byte *pattern, size_t len )
{
ushort *dist;
int i;
dist = m_alloc_clear( 256 * sizeof *dist );
for(i=0; i < 256; i++ )
dist[i] = len;
for(i=0; i < len-1; i++ )
dTbl[p[i]] = len-i-1;
return dist;
}
/****************
* Search BUF of BUFLEN for pattern P of length PATLEN.
* dist is the Boyer/Moore distance table of 256 Elements,
* case insensitive search is done if IGNCASE is true (In this case
* the distance table has to compiled from uppercase chacaters and
* PAT must also be uppercase.
* Returns: Prt to maching string in BUF, or NULL if not found.
*/
static const *
do_bm_search( const byte *buf, size_t buflen,
const byte *pat, size_t patlen, size_t *dist, int igncase )
{
int i, j, k;
if( igncase ) {
int c, c1;
for( i = --patlen; i < buflen; i += dist[c1] )
for( j=patlen, k=i, c1=c=toupper(buf[k]); c == pat[j];
j--, k--, c=toupper(buf[k]) ) {
if( !j )
return buf+k;
}
}
else {
for( i = --patlen; i < buflen; i += dist[buf[i]] )
for( j=patlen, k=i; buf[k] == pat[j]; j--, k-- ) {
if( !j )
return buf+k;
}
}
return NULL;
}
typedef struct {
size_t dist[256];
} *SCAN_USER_HANDLE;
static SCAN_USER_HANDLE
scan_user_file_open( const byte *name )
{
SCAN_USER_HANDLE hd;
size_t *dist;
int i;
hd = m_alloc_clear( sizeof *hd );
dist = hd->dist;
/* compile the distance table */
for(i=0; i < 256; i++ )
dist[i] = len;
for(i=0; i < len-1; i++ )
dTbl[p[i]] = len-i-1;
/* setup other things */
return hd;
}
static int
scan_user_file_close( SCAN_USER_HANDLE hd )
{
m_free( hd );
}
static int
scan_user_file_read( SCAN_USER_HANDLE hd, byte *fpr )
{
char record[1000];
/* read a record */
}
#endif
/****************************************************************
********** Functions which operates on regular keyrings ********
****************************************************************/
static int
cmp_seckey( PKT_secret_key *req_sk, PKT_secret_key *sk )
{
int n,i;
assert( req_sk->pubkey_algo == sk->pubkey_algo );
n = pubkey_get_nskey( req_sk->pubkey_algo );
for(i=0; i < n; i++ ) {
if( mpi_cmp( req_sk->skey[i], sk->skey[i] ) )
return -1;
}
return 0;
}
static int
cmp_pubkey( PKT_public_key *req_pk, PKT_public_key *pk )
{
int n, i;
assert( req_pk->pubkey_algo == pk->pubkey_algo );
n = pubkey_get_npkey( req_pk->pubkey_algo );
for(i=0; i < n; i++ ) {
if( mpi_cmp( req_pk->pkey[i], pk->pkey[i] ) )
return -1;
}
return 0;
}
/****************
* search one keyring, return 0 if found, -1 if not found or an errorcode.
*/
static int
keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
{
int rc;
PACKET pkt;
int save_mode;
ulong offset;
int pkttype = req->pkttype;
PKT_public_key *req_pk = req->pkt.public_key;
PKT_secret_key *req_sk = req->pkt.secret_key;
init_packet(&pkt);
save_mode = set_packet_list_mode(0);
kbpos->rt = rt_RING;
+ kbpos->valid = 0;
- #if __MINGW32__
+ #if __MINGW32__ || 1
assert(!iobuf);
iobuf = iobuf_open( fname );
if( !iobuf ) {
log_error("%s: can't open keyring file\n", fname);
rc = G10ERR_KEYRING_OPEN;
goto leave;
}
#else
if( iobuf_seek( iobuf, 0 ) ) {
log_error("can't rewind keyring file\n");
rc = G10ERR_KEYRING_OPEN;
goto leave;
}
#endif
while( !(rc=search_packet(iobuf, &pkt, pkttype, &offset)) ) {
if( pkt.pkttype == PKT_SECRET_KEY ) {
PKT_secret_key *sk = pkt.pkt.secret_key;
if( req_sk->timestamp == sk->timestamp
&& req_sk->pubkey_algo == sk->pubkey_algo
&& !cmp_seckey( req_sk, sk) )
break; /* found */
}
else if( pkt.pkttype == PKT_PUBLIC_KEY ) {
PKT_public_key *pk = pkt.pkt.public_key;
if( req_pk->timestamp == pk->timestamp
&& req_pk->pubkey_algo == pk->pubkey_algo
&& !cmp_pubkey( req_pk, pk ) )
break; /* found */
}
else
BUG();
free_packet(&pkt);
}
- if( !rc )
+ if( !rc ) {
kbpos->offset = offset;
+ kbpos->valid = 1;
+ }
leave:
free_packet(&pkt);
set_packet_list_mode(save_mode);
- #if __MINGW32__
+ #if __MINGW32__ || 1
iobuf_close(iobuf);
#endif
return rc;
}
static int
keyring_read( KBPOS *kbpos, KBNODE *ret_root )
{
PACKET *pkt;
int rc;
RESTBL *rentry;
KBNODE root = NULL;
IOBUF a;
int in_cert = 0;
if( !(rentry=check_pos(kbpos)) )
return G10ERR_GENERAL;
a = iobuf_open( rentry->fname );
if( !a ) {
log_error("can't open '%s'\n", rentry->fname );
return G10ERR_OPEN_FILE;
}
+ if( !kbpos->valid )
+ log_debug("kbpos not valid in keyring_read, want %d\n", (int)kbpos->offset );
if( iobuf_seek( a, kbpos->offset ) ) {
log_error("can't seek to %lu\n", kbpos->offset);
iobuf_close(a);
return G10ERR_KEYRING_OPEN;
}
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
kbpos->count=0;
while( (rc=parse_packet(a, pkt)) != -1 ) {
if( rc ) { /* ignore errors */
if( rc != G10ERR_UNKNOWN_PACKET ) {
log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
rc = G10ERR_INV_KEYRING;
goto ready;
}
kbpos->count++;
free_packet( pkt );
init_packet( pkt );
continue;
}
/* make a linked list of all packets */
switch( pkt->pkttype ) {
+ case PKT_COMPRESSED:
+ log_error("skipped compressed packet in keyring\n" );
+ free_packet(pkt);
+ init_packet(pkt);
+ break;
+
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
if( in_cert )
goto ready;
in_cert = 1;
default:
kbpos->count++;
if( !root )
root = new_kbnode( pkt );
else
add_kbnode( root, new_kbnode( pkt ) );
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
break;
}
}
ready:
+ kbpos->valid = 0;
if( rc == -1 && root )
rc = 0;
if( rc )
release_kbnode( root );
else
*ret_root = root;
free_packet( pkt );
m_free( pkt );
iobuf_close(a);
return rc;
}
static int
keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs )
{
PACKET *pkt;
int rc;
RESTBL *rentry;
KBNODE root = NULL;
if( !(rentry=check_pos(kbpos)) )
return G10ERR_GENERAL;
if( kbpos->pkt ) {
root = new_kbnode( kbpos->pkt );
kbpos->pkt = NULL;
}
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
while( (rc=parse_packet(kbpos->fp, pkt)) != -1 ) {
if( rc ) { /* ignore errors */
if( rc != G10ERR_UNKNOWN_PACKET ) {
log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
rc = G10ERR_INV_KEYRING;
goto ready;
}
free_packet( pkt );
init_packet( pkt );
continue;
}
/* make a linked list of all packets */
switch( pkt->pkttype ) {
+ case PKT_COMPRESSED:
+ log_error("skipped compressed packet in keyring\n" );
+ free_packet(pkt);
+ init_packet(pkt);
+ break;
+
case PKT_PUBLIC_KEY:
case PKT_SECRET_KEY:
if( root ) { /* store this packet */
kbpos->pkt = pkt;
pkt = NULL;
goto ready;
}
root = new_kbnode( pkt );
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
break;
default:
/* skip pakets at the beginning of a keyring, until we find
* a start packet; issue a warning if it is not a comment */
if( !root && pkt->pkttype != PKT_COMMENT
&& pkt->pkttype != PKT_OLD_COMMENT ) {
break;
}
if( !root || (skipsigs && ( pkt->pkttype == PKT_SIGNATURE
||pkt->pkttype == PKT_COMMENT
||pkt->pkttype == PKT_OLD_COMMENT )) ) {
init_packet(pkt);
break;
}
add_kbnode( root, new_kbnode( pkt ) );
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
break;
}
}
ready:
if( rc == -1 && root )
rc = 0;
if( rc )
release_kbnode( root );
else
*ret_root = root;
free_packet( pkt );
m_free( pkt );
return rc;
}
/****************
* Perform insert/delete/update operation.
* mode 1 = insert
* 2 = delete
* 3 = update
*/
static int
keyring_copy( KBPOS *kbpos, int mode, KBNODE root )
{
RESTBL *rentry;
IOBUF fp, newfp;
int rc=0;
char *bakfname = NULL;
char *tmpfname = NULL;
if( !(rentry = check_pos( kbpos )) )
return G10ERR_GENERAL;
if( kbpos->fp )
BUG(); /* not allowed with such a handle */
if( !keyring_lock );
keyring_lock = make_dotlock( rentry->fname, -1 );
if( !keyring_lock )
log_fatal("can't lock '%s'\n", rentry->fname );
/* open the source file */
fp = iobuf_open( rentry->fname );
if( mode == 1 && !fp && errno == ENOENT ) { /* no file yet */
KBNODE kbctx, node;
/* insert: create a new file */
newfp = iobuf_create( rentry->fname );
if( !newfp ) {
log_error(_("%s: can't create: %s\n"), rentry->fname, strerror(errno));
if( !opt.lock_once ) {
release_dotlock( keyring_lock );
keyring_lock = NULL;
}
return G10ERR_OPEN_FILE;
}
else
log_info(_("%s: keyring created\n"), rentry->fname );
kbctx=NULL;
while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
if( (rc = build_packet( newfp, node->pkt )) ) {
log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, g10_errstr(rc) );
iobuf_cancel(newfp);
if( !opt.lock_once ) {
release_dotlock( keyring_lock );
keyring_lock = NULL;
}
return G10ERR_WRITE_FILE;
}
}
if( iobuf_close(newfp) ) {
log_error("%s: close failed: %s\n", rentry->fname, strerror(errno));
if( !opt.lock_once ) {
release_dotlock( keyring_lock );
keyring_lock = NULL;
}
return G10ERR_CLOSE_FILE;
}
if( chmod( rentry->fname, S_IRUSR | S_IWUSR ) ) {
log_error("%s: chmod failed: %s\n",
rentry->fname, strerror(errno) );
if( !opt.lock_once ) {
release_dotlock( keyring_lock );
keyring_lock = NULL;
}
return G10ERR_WRITE_FILE;
}
return 0;
}
if( !fp ) {
log_error("%s: can't open: %s\n", rentry->fname, strerror(errno) );
rc = G10ERR_OPEN_FILE;
goto leave;
}
/* create the new file */
#ifdef __MINGW32__
/* Here is another Windoze bug?:
* you cant rename("pubring.gpg.tmp", "pubring.gpg");
* but rename("pubring.gpg.tmp", "pubring.aaa");
* works. So we replace .gpg by .bak or .tmp
*/
if( strlen(rentry->fname) > 4
&& !strcmp(rentry->fname+strlen(rentry->fname)-4, ".gpg") ) {
bakfname = m_alloc( strlen( rentry->fname ) + 1 );
strcpy(bakfname,rentry->fname);
strcpy(bakfname+strlen(rentry->fname)-4, ".bak");
tmpfname = m_alloc( strlen( rentry->fname ) + 1 );
strcpy(tmpfname,rentry->fname);
strcpy(tmpfname+strlen(rentry->fname)-4, ".tmp");
}
else { /* file does not end with gpg; hmmm */
bakfname = m_alloc( strlen( rentry->fname ) + 5 );
strcpy(stpcpy(bakfname,rentry->fname),".bak");
tmpfname = m_alloc( strlen( rentry->fname ) + 5 );
strcpy(stpcpy(tmpfname,rentry->fname),".tmp");
}
#else
bakfname = m_alloc( strlen( rentry->fname ) + 2 );
strcpy(stpcpy(bakfname,rentry->fname),"~");
tmpfname = m_alloc( strlen( rentry->fname ) + 5 );
strcpy(stpcpy(tmpfname,rentry->fname),".tmp");
#endif
newfp = iobuf_create( tmpfname );
if( !newfp ) {
log_error("%s: can't create: %s\n", tmpfname, strerror(errno) );
iobuf_close(fp);
rc = G10ERR_OPEN_FILE;
goto leave;
}
if( mode == 1 ) { /* insert */
/* copy everything to the new file */
rc = copy_all_packets( fp, newfp );
if( rc != -1 ) {
log_error("%s: copy to %s failed: %s\n",
rentry->fname, tmpfname, g10_errstr(rc) );
iobuf_close(fp);
iobuf_cancel(newfp);
goto leave;
}
rc = 0;
}
if( mode == 2 || mode == 3 ) { /* delete or update */
/* copy first part to the new file */
rc = copy_some_packets( fp, newfp, kbpos->offset );
if( rc ) { /* should never get EOF here */
log_error("%s: copy to %s failed: %s\n",
rentry->fname, tmpfname, g10_errstr(rc) );
iobuf_close(fp);
iobuf_cancel(newfp);
goto leave;
}
/* skip this keyblock */
assert( kbpos->count );
rc = skip_some_packets( fp, kbpos->count );
if( rc ) {
log_error("%s: skipping %u packets failed: %s\n",
rentry->fname, kbpos->count, g10_errstr(rc));
iobuf_close(fp);
iobuf_cancel(newfp);
goto leave;
}
}
if( mode == 1 || mode == 3 ) { /* insert or update */
KBNODE kbctx, node;
/* append the new data */
kbctx=NULL;
while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
if( (rc = build_packet( newfp, node->pkt )) ) {
log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, g10_errstr(rc) );
iobuf_close(fp);
iobuf_cancel(newfp);
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
+ kbpos->valid = 0;
}
if( mode == 2 || mode == 3 ) { /* delete or update */
/* copy the rest */
rc = copy_all_packets( fp, newfp );
if( rc != -1 ) {
log_error("%s: copy to %s failed: %s\n",
rentry->fname, tmpfname, g10_errstr(rc) );
iobuf_close(fp);
iobuf_cancel(newfp);
goto leave;
}
rc = 0;
}
/* close both files */
if( iobuf_close(fp) ) {
log_error("%s: close failed: %s\n", rentry->fname, strerror(errno) );
rc = G10ERR_CLOSE_FILE;
goto leave;
}
if( iobuf_close(newfp) ) {
log_error("%s: close failed: %s\n", tmpfname, strerror(errno) );
rc = G10ERR_CLOSE_FILE;
goto leave;
}
/* if the new file is a secring, restrict the permissions */
#ifndef __MINGW32__
if( rentry->secret ) {
if( chmod( tmpfname, S_IRUSR | S_IWUSR ) ) {
log_error("%s: chmod failed: %s\n",
tmpfname, strerror(errno) );
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
#endif
/* rename and make backup file */
if( !rentry->secret ) { /* but not for secret keyrings */
#ifdef __MINGW32__
remove( bakfname );
#endif
if( rename( rentry->fname, bakfname ) ) {
log_error("%s: rename to %s failed: %s\n",
rentry->fname, bakfname, strerror(errno) );
rc = G10ERR_RENAME_FILE;
goto leave;
}
}
#ifdef __MINGW32__
remove( rentry->fname );
#endif
if( rename( tmpfname, rentry->fname ) ) {
log_error("%s: rename to %s failed: %s\n",
tmpfname, rentry->fname,strerror(errno) );
rc = G10ERR_RENAME_FILE;
if( rentry->secret ) {
log_info(_(
"WARNING: 2 files with confidential information exists.\n"));
log_info(_("%s is the unchanged one\n"), rentry->fname );
log_info(_("%s is the new one\n"), tmpfname );
log_info(_("Please fix this possible security flaw\n"));
}
goto leave;
}
leave:
if( !opt.lock_once ) {
release_dotlock( keyring_lock );
keyring_lock = NULL;
}
m_free(bakfname);
m_free(tmpfname);
return rc;
}
#ifdef HAVE_LIBGDBM
/****************************************************************
********** Functions which operates on GDM files ***************
****************************************************************/
#if MAX_FINGERPRINT_LEN > 20
#error A GDBM keyring assumes that fingerprints are less than 21
#endif
/****************
* Insert the keyblock into the GDBM database
*/
static int
do_gdbm_store( KBPOS *kbpos, KBNODE root, int update )
{
RESTBL *rentry;
PKT_public_key *pk;
KBNODE kbctx, node;
IOBUF fp = NULL;
byte fpr[20];
byte contbuf[21];
byte keybuf[21];
size_t fprlen;
datum key, content;
int i, rc;
if( !(rentry = check_pos( kbpos )) )
return G10ERR_GENERAL;
/* construct the fingerprint which is used as the primary key */
node = find_kbnode( root, PKT_PUBLIC_KEY );
if( !node )
log_bug("a gdbm database can't store secret keys\n");
pk = node->pkt->pkt.public_key;
fingerprint_from_pk( pk, fpr, &fprlen );
for(i=fprlen; i < DIM(fpr); i++ )
fpr[i] = 0;
/* build the keyblock */
kbctx=NULL;
fp = iobuf_temp();
iobuf_put( fp, 1 ); /* data is a keyblock */
while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
if( (rc = build_packet( fp, node->pkt )) ) {
log_error("build_packet(%d) failed: %s\n",
node->pkt->pkttype, g10_errstr(rc) );
rc = G10ERR_WRITE_FILE;
goto leave;
}
}
/* store data and key */
*keybuf = 1; /* key is a padded fingerprint */
memcpy(keybuf+1, fpr, 20 );
key.dptr = keybuf;
key.dsize = 21;
content.dptr = iobuf_get_temp_buffer( fp );
content.dsize = iobuf_get_temp_length( fp );
rc = gdbm_store( rentry->dbf, key, content,
update? GDBM_REPLACE : GDBM_INSERT );
if( rc == 1 && !update )
rc = gdbm_store( rentry->dbf, key, content, GDBM_REPLACE );
if( rc ) {
log_error("%s: gdbm_store failed: %s\n", rentry->fname,
rc == 1 ? "already stored"
: gdbm_strerror(gdbm_errno) );
rc = G10ERR_WRITE_FILE;
goto leave;
}
/* now store all keyids */
*contbuf = 2; /* data is a list of fingerprints */
memcpy(contbuf+1, fpr, 20 );
content.dptr = contbuf;
content.dsize= 21;
kbctx=NULL;
while( (node = walk_kbnode( root, &kbctx, 0 )) ) {
if( node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
u32 aki[2];
keyid_from_pk( node->pkt->pkt.public_key, aki );
*keybuf = 2; /* key is a 8 byte keyid */
u32tobuf( keybuf+1 , aki[0] );
u32tobuf( keybuf+5, aki[1] );
key.dptr = keybuf;
key.dsize= 9;
/* fixme: must be more clever when a insert failed:
* build a list of fingerprints in this case */
rc = gdbm_store( rentry->dbf, key, content,
update? GDBM_REPLACE : GDBM_INSERT );
if( rc ) {
log_info("%s: gdbm_store keyid failed: %s\n", rentry->fname,
rc == 1 ? "already stored"
: gdbm_strerror(gdbm_errno) );
rc = 0;
}
}
}
leave:
iobuf_close(fp); /* don't need a cancel because it is a temp iobuf */
return rc;
}
/****************
* search one keybox, return 0 if found, -1 if not found or an errorcode.
*/
static int
do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos, const byte *fpr, int fprlen )
{
byte *keybuf = kbpos->keybuf;
datum key;
int i;
*keybuf = 1;
for(i=0; i < fprlen; i++ )
keybuf[i+1] = fpr[i];
for(; i < 20; i++ )
keybuf[i+1] = 0;
/* fetch the data */
key.dptr = keybuf;
key.dsize = 21;
if( !gdbm_exists( dbf, key ) )
return -1; /* not found */
return 0;
}
/****************
* locate by keyid.
* FIXME: we must have a way to enumerate thru the list opf fingerprints
*/
static int
do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid )
{
byte keybuf[9];
datum key, content;
int rc;
/* construct the fingerprint which is used as the primary key */
*keybuf = 2;
u32tobuf( keybuf+1, keyid[0] );
u32tobuf( keybuf+5, keyid[1] );
/* fetch the data */
key.dptr = keybuf;
key.dsize = 9;
content = gdbm_fetch( dbf, key );
if( !content.dptr )
return -1;
if( content.dsize < 2 ) {
log_error("gdbm_fetch did not return enough data\n" );
free( content.dptr ); /* can't use m_free() here */
return G10ERR_INV_KEYRING;
}
if( *content.dptr != 2 ) {
log_error("gdbm_fetch returned unexpected type %d\n",
*(byte*)content.dptr );
free( content.dptr ); /* can't use m_free() here */
return G10ERR_INV_KEYRING;
}
if( content.dsize < 21 ) {
log_error("gdbm_fetch did not return a complete fingerprint\n" );
free( content.dptr ); /* can't use m_free() here */
return G10ERR_INV_KEYRING;
}
if( content.dsize > 21 )
log_info("gdbm_fetch: WARNING: more than one fingerprint\n" );
rc = do_gdbm_locate( dbf, kbpos, content.dptr+1, 20 );
free( content.dptr ); /* can't use m_free() here */
return rc;
}
static int
do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root )
{
PACKET *pkt;
int rc;
RESTBL *rentry;
KBNODE root = NULL;
IOBUF a;
datum key, content;
if( !(rentry=check_pos(kbpos)) )
return G10ERR_GENERAL;
key.dptr = kbpos->keybuf;
key.dsize = 21;
content = gdbm_fetch( rentry->dbf, key );
if( !content.dptr ) {
log_error("gdbm_fetch failed: %s\n", gdbm_strerror(gdbm_errno) );
return G10ERR_INV_KEYRING;
}
if( content.dsize < 2 ) {
log_error("gdbm_fetch did not return enough data\n" );
free( content.dptr ); /* can't use m_free() here */
return G10ERR_INV_KEYRING;
}
if( *content.dptr != 1 ) {
log_error("gdbm_fetch returned unexpected type %d\n",
*(byte*)content.dptr );
free( content.dptr ); /* can't use m_free() here */
return G10ERR_INV_KEYRING;
}
a = iobuf_temp_with_content( content.dptr+1, content.dsize-1 );
free( content.dptr ); /* can't use m_free() here */
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
kbpos->count=0;
while( (rc=parse_packet(a, pkt)) != -1 ) {
if( rc ) { /* ignore errors */
if( rc != G10ERR_UNKNOWN_PACKET ) {
log_error("read_keyblock: read error: %s\n", g10_errstr(rc) );
rc = G10ERR_INV_KEYRING;
break;
}
kbpos->count++;
free_packet( pkt );
init_packet( pkt );
continue;
}
/* make a linked list of all packets */
kbpos->count++;
if( !root )
root = new_kbnode( pkt );
else
add_kbnode( root, new_kbnode( pkt ) );
pkt = m_alloc( sizeof *pkt );
init_packet(pkt);
}
if( rc == -1 && root )
rc = 0;
if( rc )
release_kbnode( root );
else
*ret_root = root;
free_packet( pkt );
m_free( pkt );
iobuf_close(a);
return rc;
}
/****************
* Enum over keyblok data
*/
static int
do_gdbm_enum( KBPOS *kbpos, KBNODE *ret_root )
{
RESTBL *rentry;
datum key, helpkey;
if( !(rentry=check_pos(kbpos)) )
return G10ERR_GENERAL;
if( !kbpos->offset ) {
kbpos->offset = 1;
key = gdbm_firstkey( rentry->dbf );
}
else {
helpkey.dptr = kbpos->keybuf;
helpkey.dsize= 21;
key = gdbm_nextkey( rentry->dbf, helpkey );
}
while( key.dptr && (!key.dsize || *key.dptr != 1) ) {
helpkey = key;
key = gdbm_nextkey( rentry->dbf, helpkey );
free( helpkey.dptr ); /* free and not m_free() ! */
}
if( !key.dptr )
return -1; /* eof */
if( key.dsize < 21 ) {
free( key.dptr ); /* free and not m_free() ! */
log_error("do_gdm_enum: key is too short\n" );
return G10ERR_INV_KEYRING;
}
memcpy( kbpos->keybuf, key.dptr, 21 );
free( key.dptr ); /* free and not m_free() ! */
return do_gdbm_read( kbpos, ret_root );
}
#endif /*HAVE_LIBGDBM*/
diff --git a/g10/seckey-cert.c b/g10/seckey-cert.c
index 1950ae0e1..6adfafdf4 100644
--- a/g10/seckey-cert.c
+++ b/g10/seckey-cert.c
@@ -1,287 +1,287 @@
/* seckey-cert.c - secret key certifucate packet handling
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "packet.h"
#include "mpi.h"
#include "keydb.h"
#include "cipher.h"
#include "main.h"
#include "options.h"
#include "i18n.h"
static int
do_check( PKT_secret_key *sk )
{
byte *buffer;
u16 csum=0;
int i, res;
unsigned nbytes;
if( sk->is_protected ) { /* remove the protection */
DEK *dek = NULL;
u32 keyid[2];
CIPHER_HANDLE cipher_hd=NULL;
PKT_secret_key *save_sk;
char save_iv[8];
if( sk->protect.algo == CIPHER_ALGO_NONE )
BUG();
if( check_cipher_algo( sk->protect.algo )
|| cipher_get_blocksize( sk->protect.algo ) != 8 ) {
log_info(_("protection algorithm %d is not supported\n"),
sk->protect.algo );
return G10ERR_CIPHER_ALGO;
}
keyid_from_sk( sk, keyid );
dek = passphrase_to_dek( keyid, sk->protect.algo,
&sk->protect.s2k, 0 );
cipher_hd = cipher_open( sk->protect.algo,
CIPHER_MODE_AUTO_CFB, 1);
cipher_setkey( cipher_hd, dek->key, dek->keylen );
cipher_setiv( cipher_hd, NULL );
m_free(dek);
save_sk = copy_secret_key( NULL, sk );
memcpy(save_iv, sk->protect.iv, 8 );
cipher_decrypt( cipher_hd, sk->protect.iv, sk->protect.iv, 8 );
csum = 0;
if( sk->version >= 4 ) {
int ndata;
byte *p, *data;
i = pubkey_get_npkey(sk->pubkey_algo);
assert( mpi_is_opaque( sk->skey[i] ) );
p = mpi_get_opaque( sk->skey[i], &ndata );
data = m_alloc_secure( ndata );
cipher_decrypt( cipher_hd, data, p, ndata );
mpi_free( sk->skey[i] ); sk->skey[i] = NULL ;
p = data;
if( ndata < 2 ) {
log_error("not enough bytes for checksum\n");
sk->csum = 0;
csum = 1;
}
else {
csum = checksum( data, ndata-2);
sk->csum = data[ndata-2] << 8 | data[ndata-1];
}
/* must check it here otherwise the mpi_read_xx would fail
* because the length das an abritary value */
if( sk->csum == csum ) {
for( ; i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
nbytes = ndata;
sk->skey[i] = mpi_read_from_buffer(p, &nbytes, 1 );
ndata -= nbytes;
p += nbytes;
}
}
m_free(data);
}
else {
for(i=pubkey_get_npkey(sk->pubkey_algo);
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
buffer = mpi_get_secure_buffer( sk->skey[i], &nbytes, NULL );
cipher_sync( cipher_hd );
assert( mpi_is_protected(sk->skey[i]) );
cipher_decrypt( cipher_hd, buffer, buffer, nbytes );
mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 );
mpi_clear_protect_flag( sk->skey[i] );
csum += checksum_mpi( sk->skey[i] );
m_free( buffer );
}
if( opt.emulate_bugs & EMUBUG_GPGCHKSUM ) {
csum = sk->csum;
}
}
cipher_close( cipher_hd );
/* now let's see whether we have used the right passphrase */
if( csum != sk->csum ) {
copy_secret_key( sk, save_sk );
free_secret_key( save_sk );
memcpy( sk->protect.iv, save_iv, 8 );
return G10ERR_BAD_PASS;
}
/* the checksum may fail, so we also check the key itself */
res = pubkey_check_secret_key( sk->pubkey_algo, sk->skey );
if( res ) {
copy_secret_key( sk, save_sk );
free_secret_key( save_sk );
memcpy( sk->protect.iv, save_iv, 8 );
return G10ERR_BAD_PASS;
}
free_secret_key( save_sk );
sk->is_protected = 0;
}
else { /* not protected, assume it is okay if the checksum is okay */
csum = 0;
for(i=pubkey_get_npkey(sk->pubkey_algo);
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
csum += checksum_mpi( sk->skey[i] );
}
if( csum != sk->csum )
return G10ERR_CHECKSUM;
}
return 0;
}
/****************
* Check the secret key
* Ask up to 3 (or n) times for a correct passphrase
*/
int
check_secret_key( PKT_secret_key *sk, int n )
{
int rc = G10ERR_BAD_PASS;
int i;
if( n < 1 )
n = 3; /* use the default value */
for(i=0; i < n && rc == G10ERR_BAD_PASS; i++ ) {
if( i )
log_error(_("Invalid passphrase; please try again ...\n"));
rc = do_check( sk );
if( have_static_passphrase() )
break;
}
return rc;
}
/****************
* check whether the secret key is protected.
* Returns: 0 not protected, -1 on error or the protection algorithm
*/
int
is_secret_key_protected( PKT_secret_key *sk )
{
return sk->is_protected? sk->protect.algo : 0;
}
/****************
* Protect the secret key with the passphrase from DEK
*/
int
protect_secret_key( PKT_secret_key *sk, DEK *dek )
{
int i,j, rc = 0;
byte *buffer;
unsigned nbytes;
u16 csum;
if( !dek )
return 0;
if( !sk->is_protected ) { /* okay, apply the protection */
CIPHER_HANDLE cipher_hd=NULL;
if( check_cipher_algo( sk->protect.algo ) )
rc = G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
else if( cipher_get_blocksize( sk->protect.algo ) != 8 )
rc = G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
else {
print_cipher_algo_note( sk->protect.algo );
cipher_hd = cipher_open( sk->protect.algo,
CIPHER_MODE_AUTO_CFB, 1 );
if( cipher_setkey( cipher_hd, dek->key, dek->keylen ) )
log_info(_("WARNING: Weak key detected"
" - please change passphrase again.\n"));
cipher_setiv( cipher_hd, NULL );
cipher_encrypt( cipher_hd, sk->protect.iv, sk->protect.iv, 8 );
if( sk->version >= 4 ) {
#define NMPIS (PUBKEY_MAX_NSKEY - PUBKEY_MAX_NPKEY)
byte *buffer[NMPIS];
unsigned nbytes[NMPIS];
unsigned nbits[NMPIS];
int ndata=0;
byte *p, *data;
for(j=0, i = pubkey_get_npkey(sk->pubkey_algo);
i < pubkey_get_nskey(sk->pubkey_algo); i++, j++ ) {
assert( !mpi_is_opaque( sk->skey[i] ) );
buffer[j] = mpi_get_buffer( sk->skey[i], &nbytes[j], NULL );
nbits[j] = mpi_get_nbits( sk->skey[i] );
ndata += nbytes[j] + 2;
}
for( ; j < NMPIS; j++ )
buffer[j] = NULL;
ndata += 2; /* for checksum */
data = m_alloc_secure( ndata );
p = data;
for(j=0; j < NMPIS && buffer[j]; j++ ) {
p[0] = nbits[j] >> 8 ;
p[1] = nbits[j];
p += 2;
memcpy(p, buffer[j], nbytes[j] );
p += nbytes[j];
m_free(buffer[j]);
}
#undef NMPIS
csum = checksum( data, ndata-2);
sk->csum = csum;
*p++ = csum >> 8;
*p++ = csum;
assert( p == data+ndata );
cipher_encrypt( cipher_hd, data, data, ndata );
for(i = pubkey_get_npkey(sk->pubkey_algo);
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
mpi_free( sk->skey[i] );
sk->skey[i] = NULL;
}
i = pubkey_get_npkey(sk->pubkey_algo);
sk->skey[i] = mpi_set_opaque(NULL, data, ndata );
}
else {
/* NOTE: we always recalculate the checksum because there
* are some test releases which calculated it wrong */
csum = 0;
for(i=pubkey_get_npkey(sk->pubkey_algo);
i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
csum += checksum_mpi_counted_nbits( sk->skey[i] );
buffer = mpi_get_buffer( sk->skey[i], &nbytes, NULL );
cipher_sync( cipher_hd );
assert( !mpi_is_protected(sk->skey[i]) );
cipher_encrypt( cipher_hd, buffer, buffer, nbytes );
mpi_set_buffer( sk->skey[i], buffer, nbytes, 0 );
mpi_set_protect_flag( sk->skey[i] );
m_free( buffer );
}
sk->csum = csum;
}
sk->is_protected = 1;
cipher_close( cipher_hd );
}
}
return rc;
}
diff --git a/g10/seskey.c b/g10/seskey.c
index b9dab28cc..bb158abc0 100644
--- a/g10/seskey.c
+++ b/g10/seskey.c
@@ -1,204 +1,204 @@
/* seskey.c - make sesssion keys etc.
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "cipher.h"
#include "mpi.h"
#include "main.h"
#include "i18n.h"
/****************
* Make a session key and put it into DEK
*/
void
make_session_key( DEK *dek )
{
CIPHER_HANDLE chd;
int i, rc;
dek->keylen = cipher_get_keylen( dek->algo ) / 8;
chd = cipher_open( dek->algo, CIPHER_MODE_AUTO_CFB, 1 );
randomize_buffer( dek->key, dek->keylen, 1 );
for(i=0; i < 16; i++ ) {
rc = cipher_setkey( chd, dek->key, dek->keylen );
if( !rc ) {
cipher_close( chd );
return;
}
log_info(_("weak key created - retrying\n") );
/* Renew the session key until we get a non-weak key. */
randomize_buffer( dek->key, dek->keylen, 1 );
}
log_fatal(_(
"cannot avoid weak key for symmetric cipher; tried %d times!\n"),
i);
}
/****************
* Encode the session key. NBITS is the number of bits which should be used
* for packing the session key.
* returns: A mpi with the session key (caller must free)
*/
MPI
encode_session_key( DEK *dek, unsigned nbits )
{
int nframe = (nbits+7) / 8;
byte *p;
byte *frame;
int i,n;
u16 csum;
MPI a;
/* the current limitation is that we can only use a session key
* whose length is a multiple of BITS_PER_MPI_LIMB
* I think we can live with that.
*/
if( dek->keylen + 7 > nframe || !nframe )
log_bug("can't encode a %d bit key in a %d bits frame\n",
dek->keylen*8, nbits );
/* We encode the session key in this way:
*
* 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes)
*
* (But how can we store the leading 0 - the external representaion
* of MPIs doesn't allow leading zeroes =:-)
*
* RND are non-zero random bytes.
* A is the cipher algorithm
* DEK is the encryption key (session key) length k depends on the
* cipher algorithm (20 is used with blowfish160).
* CSUM is the 16 bit checksum over the DEK
*/
csum = 0;
for( p = dek->key, i=0; i < dek->keylen; i++ )
csum += *p++;
frame = m_alloc_secure( nframe );
n = 0;
frame[n++] = 0;
frame[n++] = 2;
i = nframe - 6 - dek->keylen;
assert( i > 0 );
p = get_random_bits( i*8, 1, 1 );
/* replace zero bytes by new values */
for(;;) {
int j, k;
byte *pp;
/* count the zero bytes */
for(j=k=0; j < i; j++ )
if( !p[j] )
k++;
if( !k )
break; /* okay: no zero bytes */
k += k/128; /* better get some more */
pp = get_random_bits( k*8, 1, 1);
for(j=0; j < i && k ; j++ )
if( !p[j] )
p[j] = pp[--k];
m_free(pp);
}
memcpy( frame+n, p, i );
m_free(p);
n += i;
frame[n++] = 0;
frame[n++] = dek->algo;
memcpy( frame+n, dek->key, dek->keylen ); n += dek->keylen;
frame[n++] = csum >>8;
frame[n++] = csum;
assert( n == nframe );
a = mpi_alloc_secure( (nframe+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB );
mpi_set_buffer( a, frame, nframe, 0 );
m_free(frame);
return a;
}
static MPI
do_encode_md( MD_HANDLE md, int algo, size_t len, unsigned nbits,
const byte *asn, size_t asnlen )
{
int nframe = (nbits+7) / 8;
byte *frame;
int i,n;
MPI a;
if( len + asnlen + 4 > nframe )
log_bug("can't encode a %d bit MD into a %d bits frame\n",
(int)(len*8), (int)nbits);
/* We encode the MD in this way:
*
* 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
*
* PAD consists of FF bytes.
*/
frame = md_is_secure(md)? m_alloc_secure( nframe ) : m_alloc( nframe );
n = 0;
frame[n++] = 0;
frame[n++] = algo;
i = nframe - len - asnlen -3 ;
assert( i > 1 );
memset( frame+n, 0xff, i ); n += i;
frame[n++] = 0;
memcpy( frame+n, asn, asnlen ); n += asnlen;
memcpy( frame+n, md_read(md, algo), len ); n += len;
assert( n == nframe );
a = md_is_secure(md)?
mpi_alloc_secure( (nframe+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB )
: mpi_alloc( (nframe+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB );
mpi_set_buffer( a, frame, nframe, 0 );
m_free(frame);
return a;
}
MPI
encode_md_value( int pubkey_algo, MD_HANDLE md, int hash_algo, unsigned nbits )
{
int algo = hash_algo? hash_algo : md_get_algo(md);
const byte *asn;
size_t asnlen, mdlen;
MPI frame;
if( pubkey_algo == PUBKEY_ALGO_DSA ) {
frame = md_is_secure(md)? mpi_alloc_secure((md_digest_length(hash_algo)
+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB )
: mpi_alloc((md_digest_length(hash_algo)
+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB );
mpi_set_buffer( frame, md_read(md, hash_algo),
md_digest_length(hash_algo), 0 );
}
else {
asn = md_asn_oid( algo, &asnlen, &mdlen );
frame = do_encode_md( md, algo, mdlen, nbits, asn, asnlen );
}
return frame;
}
diff --git a/g10/sig-check.c b/g10/sig-check.c
index 63bdda220..355f6cdef 100644
--- a/g10/sig-check.c
+++ b/g10/sig-check.c
@@ -1,351 +1,351 @@
/* sig-check.c - Check a signature
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "packet.h"
#include "memory.h"
#include "mpi.h"
#include "keydb.h"
#include "cipher.h"
#include "main.h"
#include "status.h"
#include "i18n.h"
struct cmp_help_context_s {
PKT_signature *sig;
MD_HANDLE md;
};
static int do_check( PKT_public_key *pk, PKT_signature *sig,
MD_HANDLE digest );
/****************
* Check the signature which is contained in SIG.
* The md5handle should be currently open, so that this function
* is able to append some data, before finalizing the digest.
*/
int
signature_check( PKT_signature *sig, MD_HANDLE digest )
{
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
int rc=0;
if( is_RSA(sig->pubkey_algo) )
write_status(STATUS_RSA_OR_IDEA);
if( get_pubkey( pk, sig->keyid ) )
rc = G10ERR_NO_PUBKEY;
else
rc = do_check( pk, sig, digest );
free_public_key( pk );
return rc;
}
/****************
* This function gets called by pubkey_verify() if the algorithm needs it.
*/
static int
cmp_help( void *opaque, MPI result )
{
#if 0 /* we do not use this anymore */
int rc=0, i, j, c, old_enc;
byte *dp;
const byte *asn;
size_t mdlen, asnlen;
struct cmp_help_context_s *ctx = opaque;
PKT_signature *sig = ctx->sig;
MD_HANDLE digest = ctx->md;
old_enc = 0;
for(i=j=0; (c=mpi_getbyte(result, i)) != -1; i++ ) {
if( !j ) {
if( !i && c != 1 )
break;
else if( i && c == 0xff )
; /* skip the padding */
else if( i && !c )
j++;
else
break;
}
else if( ++j == 18 && c != 1 )
break;
else if( j == 19 && c == 0 ) {
old_enc++;
break;
}
}
if( old_enc ) {
log_error("old encoding scheme is not supported\n");
return G10ERR_GENERAL;
}
if( (rc=check_digest_algo(sig->digest_algo)) )
return rc; /* unsupported algo */
asn = md_asn_oid( sig->digest_algo, &asnlen, &mdlen );
for(i=mdlen,j=asnlen-1; (c=mpi_getbyte(result, i)) != -1 && j >= 0;
i++, j-- )
if( asn[j] != c )
break;
if( j != -1 || mpi_getbyte(result, i) )
return G10ERR_BAD_PUBKEY; /* ASN is wrong */
for(i++; (c=mpi_getbyte(result, i)) != -1; i++ )
if( c != 0xff )
break;
i++;
if( c != sig->digest_algo || mpi_getbyte(result, i) ) {
/* Padding or leading bytes in signature is wrong */
return G10ERR_BAD_PUBKEY;
}
if( mpi_getbyte(result, mdlen-1) != sig->digest_start[0]
|| mpi_getbyte(result, mdlen-2) != sig->digest_start[1] ) {
/* Wrong key used to check the signature */
return G10ERR_BAD_PUBKEY;
}
dp = md_read( digest, sig->digest_algo );
for(i=mdlen-1; i >= 0; i--, dp++ ) {
if( mpi_getbyte( result, i ) != *dp )
return G10ERR_BAD_SIGN;
}
return 0;
#else
return -1;
#endif
}
static int
do_check( PKT_public_key *pk, PKT_signature *sig, MD_HANDLE digest )
{
MPI result = NULL;
int rc=0;
struct cmp_help_context_s ctx;
u32 cur_time;
if( pk->version == 4 && pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) {
log_info(_("this is a PGP generated "
"ElGamal key which is NOT secure for signatures!\n"));
return G10ERR_PUBKEY_ALGO;
}
if( pk->timestamp > sig->timestamp )
return G10ERR_TIME_CONFLICT; /* pubkey newer than signature */
cur_time = make_timestamp();
if( pk->timestamp > cur_time ) {
log_info(_("public key created in future (time warp or clock problem)\n"));
return G10ERR_TIME_CONFLICT;
}
if( pk->expiredate && pk->expiredate < cur_time ) {
log_info(_("NOTE: signature key expired %s\n"),
asctimestamp( pk->expiredate ) );
write_status(STATUS_SIGEXPIRED);
}
if( (rc=check_digest_algo(sig->digest_algo)) )
return rc;
if( (rc=check_pubkey_algo(sig->pubkey_algo)) )
return rc;
/* make sure the digest algo is enabled (in case of a detached signature)*/
md_enable( digest, sig->digest_algo );
/* complete the digest */
if( sig->version >= 4 )
md_putc( digest, sig->version );
md_putc( digest, sig->sig_class );
if( sig->version < 4 ) {
u32 a = sig->timestamp;
md_putc( digest, (a >> 24) & 0xff );
md_putc( digest, (a >> 16) & 0xff );
md_putc( digest, (a >> 8) & 0xff );
md_putc( digest, a & 0xff );
}
else {
byte buf[6];
size_t n;
md_putc( digest, sig->pubkey_algo );
md_putc( digest, sig->digest_algo );
if( sig->hashed_data ) {
n = (sig->hashed_data[0] << 8) | sig->hashed_data[1];
md_write( digest, sig->hashed_data, n+2 );
n += 6;
}
else
n = 6;
/* add some magic */
buf[0] = sig->version;
buf[1] = 0xff;
buf[2] = n >> 24;
buf[3] = n >> 16;
buf[4] = n >> 8;
buf[5] = n;
md_write( digest, buf, 6 );
}
md_final( digest );
result = encode_md_value( pk->pubkey_algo, digest, sig->digest_algo,
mpi_get_nbits(pk->pkey[0]));
ctx.sig = sig;
ctx.md = digest;
rc = pubkey_verify( pk->pubkey_algo, result, sig->data, pk->pkey,
cmp_help, &ctx );
mpi_free( result );
if( !rc && sig->flags.unknown_critical ) {
log_info(_("assuming bad signature due to an unknown critical bit\n"));
rc = G10ERR_BAD_SIGN;
}
sig->flags.checked = 1;
sig->flags.valid = !rc;
return rc;
}
static void
hash_uid_node( KBNODE unode, MD_HANDLE md, PKT_signature *sig )
{
PKT_user_id *uid = unode->pkt->pkt.user_id;
assert( unode->pkt->pkttype == PKT_USER_ID );
if( sig->version >=4 ) {
byte buf[5];
buf[0] = 0xb4; /* indicates a userid packet */
buf[1] = uid->len >> 24; /* always use 4 length bytes */
buf[2] = uid->len >> 16;
buf[3] = uid->len >> 8;
buf[4] = uid->len;
md_write( md, buf, 5 );
}
md_write( md, uid->name, uid->len );
}
/****************
* check the signature pointed to by NODE. This is a key signature.
* If the function detects a self-signature, it uses the PK from
* ROOT and does not read any public key.
*/
int
check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
{
MD_HANDLE md;
PKT_public_key *pk;
PKT_signature *sig;
int algo;
int rc;
if( is_selfsig )
*is_selfsig = 0;
assert( node->pkt->pkttype == PKT_SIGNATURE );
assert( root->pkt->pkttype == PKT_PUBLIC_KEY );
pk = root->pkt->pkt.public_key;
sig = node->pkt->pkt.signature;
algo = sig->digest_algo;
if( (rc=check_digest_algo(algo)) )
return rc;
if( sig->sig_class == 0x20 ) {
md = md_open( algo, 0 );
hash_public_key( md, pk );
rc = do_check( pk, sig, md );
md_close(md);
}
else if( sig->sig_class == 0x28 ) { /* subkey revocation */
KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY );
if( snode ) {
md = md_open( algo, 0 );
hash_public_key( md, pk );
hash_public_key( md, snode->pkt->pkt.public_key );
rc = do_check( pk, sig, md );
md_close(md);
}
else {
log_error("no subkey for subkey revocation packet\n");
rc = G10ERR_SIG_CLASS;
}
}
else if( sig->sig_class == 0x18 ) {
KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY );
if( snode ) {
if( is_selfsig ) { /* does this make sense????? */
u32 keyid[2]; /* it should always be a selfsig */
keyid_from_pk( pk, keyid );
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
*is_selfsig = 1;
}
md = md_open( algo, 0 );
hash_public_key( md, pk );
hash_public_key( md, snode->pkt->pkt.public_key );
rc = do_check( pk, sig, md );
md_close(md);
}
else {
log_error("no subkey for key signature packet\n");
rc = G10ERR_SIG_CLASS;
}
}
else {
KBNODE unode = find_prev_kbnode( root, node, PKT_USER_ID );
if( unode ) {
u32 keyid[2];
keyid_from_pk( pk, keyid );
md = md_open( algo, 0 );
/*md_start_debug(md, "check");*/
hash_public_key( md, pk );
hash_uid_node( unode, md, sig );
if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] ) {
if( is_selfsig )
*is_selfsig = 1;
rc = do_check( pk, sig, md );
}
else
rc = signature_check( sig, md );
md_close(md);
}
else {
log_error("no user id for key signature packet\n");
rc = G10ERR_SIG_CLASS;
}
}
return rc;
}
diff --git a/g10/sign.c b/g10/sign.c
index f3373ed4f..8a9ef0bba 100644
--- a/g10/sign.c
+++ b/g10/sign.c
@@ -1,843 +1,843 @@
/* sign.c - sign data
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "options.h"
#include "packet.h"
#include "errors.h"
#include "iobuf.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "main.h"
#include "filter.h"
#include "ttyio.h"
#include "trustdb.h"
#include "i18n.h"
static int
do_sign( PKT_secret_key *sk, PKT_signature *sig,
MD_HANDLE md, int digest_algo )
{
MPI frame;
byte *dp;
int rc;
print_pubkey_algo_note(sk->pubkey_algo);
if( !digest_algo )
digest_algo = md_get_algo(md);
print_digest_algo_note( digest_algo );
dp = md_read( md, digest_algo );
sig->digest_algo = digest_algo;
sig->digest_start[0] = dp[0];
sig->digest_start[1] = dp[1];
frame = encode_md_value( sk->pubkey_algo, md,
digest_algo, mpi_get_nbits(sk->skey[0]));
rc = pubkey_sign( sk->pubkey_algo, sig->data, frame, sk->skey );
mpi_free(frame);
if( rc )
log_error(_("signing failed: %s\n"), g10_errstr(rc) );
else {
if( opt.verbose ) {
char *ustr = get_user_id_string( sig->keyid );
log_info(_("%s signature from: %s\n"),
pubkey_algo_to_string(sk->pubkey_algo), ustr );
m_free(ustr);
}
}
return rc;
}
int
complete_sig( PKT_signature *sig, PKT_secret_key *sk, MD_HANDLE md )
{
int rc=0;
if( !(rc=check_secret_key( sk, 0 )) )
rc = do_sign( sk, sig, md, 0 );
/* fixme: should we check whether the signature is okay?
* maybe by using an option */
return rc;
}
static int
hash_for(int pubkey_algo )
{
if( opt.def_digest_algo )
return opt.def_digest_algo;
if( pubkey_algo == PUBKEY_ALGO_DSA )
return DIGEST_ALGO_SHA1;
if( pubkey_algo == PUBKEY_ALGO_RSA )
return DIGEST_ALGO_MD5;
return DEFAULT_DIGEST_ALGO;
}
static int
only_old_style( SK_LIST sk_list )
{
SK_LIST sk_rover = NULL;
int old_style = 0;
/* if there are only old style capable key we use the old sytle */
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
PKT_secret_key *sk = sk_rover->sk;
if( sk->pubkey_algo == PUBKEY_ALGO_RSA && sk->version < 4 )
old_style = 1;
else
return 0;
}
return old_style;
}
/****************
* Sign the files whose names are in FILENAME.
* If DETACHED has the value true,
* make a detached signature. If FILENAMES->d is NULL read from stdin
* and ignore the detached mode. Sign the file with all secret keys
* which can be taken from LOCUSR, if this is NULL, use the default one
* If ENCRYPT is true, use REMUSER (or ask if it is NULL) to encrypt the
* signed data for these users.
* If OUTFILE is not NULL; this file is used for output and the function
* does not ask for overwrite permission; output is then always
* uncompressed, non-armored and in binary mode.
*/
int
sign_file( STRLIST filenames, int detached, STRLIST locusr,
int encrypt, STRLIST remusr, const char *outfile )
{
const char *fname;
armor_filter_context_t afx;
compress_filter_context_t zfx;
md_filter_context_t mfx;
text_filter_context_t tfx;
encrypt_filter_context_t efx;
IOBUF inp = NULL, out = NULL;
PACKET pkt;
PKT_plaintext *pt = NULL;
u32 filesize;
int rc = 0;
PK_LIST pk_list = NULL;
SK_LIST sk_list = NULL;
SK_LIST sk_rover = NULL;
int multifile = 0;
int old_style = opt.rfc1991;
int compr_algo = -1; /* unknown */
memset( &afx, 0, sizeof afx);
memset( &zfx, 0, sizeof zfx);
memset( &mfx, 0, sizeof mfx);
memset( &tfx, 0, sizeof tfx);
memset( &efx, 0, sizeof efx);
init_packet( &pkt );
if( filenames ) {
fname = filenames->d;
multifile = !!filenames->next;
}
else
fname = NULL;
if( fname && filenames->next && (!detached || encrypt) )
log_bug("multiple files can only be detached signed");
if( (rc=build_sk_list( locusr, &sk_list, 1, PUBKEY_USAGE_SIG )) )
goto leave;
if( !old_style )
old_style = only_old_style( sk_list );
if( encrypt ) {
if( (rc=build_pk_list( remusr, &pk_list, PUBKEY_USAGE_ENC )) )
goto leave;
if( !old_style )
compr_algo = select_algo_from_prefs( pk_list, PREFTYPE_COMPR );
}
/* prepare iobufs */
if( multifile ) /* have list of filenames */
inp = NULL; /* we do it later */
else if( !(inp = iobuf_open(fname)) ) {
log_error("can't open %s: %s\n", fname? fname: "[stdin]",
strerror(errno) );
rc = G10ERR_OPEN_FILE;
goto leave;
}
if( outfile ) {
if( !(out = iobuf_create( outfile )) ) {
log_error(_("can't create %s: %s\n"), outfile, strerror(errno) );
rc = G10ERR_CREATE_FILE;
goto leave;
}
else if( opt.verbose )
log_info(_("writing to '%s'\n"), outfile );
}
else if( (rc = open_outfile( fname, opt.armor? 1: detached? 2:0, &out )))
goto leave;
/* prepare to calculate the MD over the input */
if( opt.textmode && !outfile )
iobuf_push_filter( inp, text_filter, &tfx );
mfx.md = md_open(0, 0);
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
PKT_secret_key *sk = sk_rover->sk;
md_enable(mfx.md, hash_for(sk->pubkey_algo));
}
if( !multifile )
iobuf_push_filter( inp, md_filter, &mfx );
if( detached && !encrypt && !opt.rfc1991 )
afx.what = 2;
if( opt.armor && !outfile )
iobuf_push_filter( out, armor_filter, &afx );
#ifdef ENABLE_COMMENT_PACKETS
else {
write_comment( out, "#created by GNUPG v" VERSION " ("
PRINTABLE_OS_NAME ")");
if( opt.comment_string )
write_comment( out, opt.comment_string );
}
#endif
if( encrypt ) {
efx.pk_list = pk_list;
/* fixme: set efx.cfx.datalen if known */
iobuf_push_filter( out, encrypt_filter, &efx );
}
if( opt.compress && !outfile && ( !detached || opt.compress_sigs) ) {
if( !compr_algo )
; /* don't use compression */
else {
if( old_style || compr_algo == 1 )
zfx.algo = 1;
iobuf_push_filter( out, compress_filter, &zfx );
}
}
if( !detached && !old_style ) {
int skcount=0;
/* loop over the secret certificates and build headers
* The specs now say that the data should be bracket by
* the onepass-sig and signature-packet; so we must build it
* here in reverse order */
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next )
skcount++;
for( ; skcount; skcount-- ) {
PKT_secret_key *sk;
PKT_onepass_sig *ops;
int i = 0;
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next )
if( ++i == skcount )
break;
sk = sk_rover->sk;
ops = m_alloc_clear( sizeof *ops );
ops->sig_class = opt.textmode && !outfile ? 0x01 : 0x00;
ops->digest_algo = hash_for(sk->pubkey_algo);
ops->pubkey_algo = sk->pubkey_algo;
keyid_from_sk( sk, ops->keyid );
ops->last = skcount == 1;
init_packet(&pkt);
pkt.pkttype = PKT_ONEPASS_SIG;
pkt.pkt.onepass_sig = ops;
rc = build_packet( out, &pkt );
free_packet( &pkt );
if( rc ) {
log_error("build onepass_sig packet failed: %s\n",
g10_errstr(rc));
goto leave;
}
}
}
/* setup the inner packet */
if( detached ) {
if( multifile ) {
STRLIST sl;
if( opt.verbose )
log_info(_("signing:") );
/* must walk reverse trough this list */
for( sl = strlist_last(filenames); sl;
sl = strlist_prev( filenames, sl ) ) {
if( !(inp = iobuf_open(sl->d)) ) {
log_error(_("can't open %s: %s\n"),
sl->d, strerror(errno) );
rc = G10ERR_OPEN_FILE;
goto leave;
}
if( opt.verbose )
fprintf(stderr, " '%s'", sl->d );
iobuf_push_filter( inp, md_filter, &mfx );
while( iobuf_get(inp) != -1 )
;
iobuf_close(inp); inp = NULL;
}
if( opt.verbose )
putc( '\n', stderr );
}
else {
/* read, so that the filter can calculate the digest */
while( iobuf_get(inp) != -1 )
;
}
}
else {
if( fname || opt.set_filename ) {
char *s = make_basename( opt.set_filename ? opt.set_filename : fname );
pt = m_alloc( sizeof *pt + strlen(s) - 1 );
pt->namelen = strlen(s);
memcpy(pt->name, s, pt->namelen );
m_free(s);
}
else { /* no filename */
pt = m_alloc( sizeof *pt - 1 );
pt->namelen = 0;
}
if( fname ) {
if( !(filesize = iobuf_get_filelength(inp)) )
log_info(_("WARNING: '%s' is an empty file\n"), fname );
/* because the text_filter modifies the length of the
* data, it is not possible to know the used length
* without a double read of the file - to avoid that
* we simple use partial length packets.
* FIXME: We have to do the double read when opt.rfc1991
* is active.
*/
if( opt.textmode && !outfile )
filesize = 0;
}
else
filesize = 0; /* stdin */
pt->timestamp = make_timestamp();
pt->mode = opt.textmode && !outfile ? 't':'b';
pt->len = filesize;
pt->new_ctb = !pt->len && !opt.rfc1991;
pt->buf = inp;
pkt.pkttype = PKT_PLAINTEXT;
pkt.pkt.plaintext = pt;
/*cfx.datalen = filesize? calc_packet_length( &pkt ) : 0;*/
if( (rc = build_packet( out, &pkt )) )
log_error("build_packet(PLAINTEXT) failed: %s\n", g10_errstr(rc) );
pt->buf = NULL;
}
/* loop over the secret certificates */
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
PKT_secret_key *sk;
PKT_signature *sig;
MD_HANDLE md;
sk = sk_rover->sk;
/* build the signature packet */
/* fixme: this code is partly duplicated in make_keysig_packet */
sig = m_alloc_clear( sizeof *sig );
sig->version = old_style || opt.force_v3_sigs ? 3 : sk->version;
keyid_from_sk( sk, sig->keyid );
sig->digest_algo = hash_for(sk->pubkey_algo);
sig->pubkey_algo = sk->pubkey_algo;
sig->timestamp = make_timestamp();
sig->sig_class = opt.textmode && !outfile? 0x01 : 0x00;
md = md_copy( mfx.md );
if( sig->version >= 4 ) {
build_sig_subpkt_from_sig( sig );
md_putc( md, sig->version );
}
md_putc( md, sig->sig_class );
if( sig->version < 4 ) {
u32 a = sig->timestamp;
md_putc( md, (a >> 24) & 0xff );
md_putc( md, (a >> 16) & 0xff );
md_putc( md, (a >> 8) & 0xff );
md_putc( md, a & 0xff );
}
else {
byte buf[6];
size_t n;
md_putc( md, sig->pubkey_algo );
md_putc( md, sig->digest_algo );
if( sig->hashed_data ) {
n = (sig->hashed_data[0] << 8) | sig->hashed_data[1];
md_write( md, sig->hashed_data, n+2 );
n += 6;
}
else
n = 6;
/* add some magic */
buf[0] = sig->version;
buf[1] = 0xff;
buf[2] = n >> 24; /* hmmm, n is only 16 bit, so this is always 0 */
buf[3] = n >> 16;
buf[4] = n >> 8;
buf[5] = n;
md_write( md, buf, 6 );
}
md_final( md );
rc = do_sign( sk, sig, md, hash_for(sig->pubkey_algo) );
md_close( md );
if( !rc ) { /* and write it */
init_packet(&pkt);
pkt.pkttype = PKT_SIGNATURE;
pkt.pkt.signature = sig;
rc = build_packet( out, &pkt );
free_packet( &pkt );
if( rc )
log_error("build signature packet failed: %s\n", g10_errstr(rc) );
}
if( rc )
goto leave;
}
leave:
if( rc )
iobuf_cancel(out);
else
iobuf_close(out);
iobuf_close(inp);
md_close( mfx.md );
release_sk_list( sk_list );
release_pk_list( pk_list );
return rc;
}
/****************
* Note: We do not calculate the hash over the last CR,LF
*/
static int
write_dash_escaped( IOBUF inp, IOBUF out, MD_HANDLE md )
{
int c;
int lastlf = 1;
int state = 0;
if( opt.not_dash_escaped ) {
lastlf = 0;
while( (c = iobuf_get(inp)) != -1 ) {
md_putc(md, c );
iobuf_put( out, c );
lastlf = c;
}
if( lastlf != '\n' ) {
/* add a missing trailing LF */
md_putc(md, '\n' );
iobuf_put( out, '\n' );
}
return 0;
}
while( (c = iobuf_get(inp)) != -1 ) {
if( lastlf ) {
if( c == '-' ) {
iobuf_put( out, c );
iobuf_put( out, ' ' );
}
else if( c == 'F' && opt.escape_from ) {
int i;
if( state >= 1 )
md_putc(md, '\r');
if( state >= 2 )
md_putc(md, '\n');
state = 0;
for( i=1; i < 5 && (c = iobuf_get(inp)) != -1; i++ ) {
if( "From "[i] != c )
break;
}
if( i < 5 ) {
iobuf_write( out, "From", i );
md_write( md, "From", i );
if( c == -1 )
break;
}
else {
iobuf_writestr( out, "- From" );
md_write( md, "From", 4 );
}
}
}
again:
switch( state ) {
case 0:
if( c == '\r' )
state = 1;
else
md_putc(md, c );
break;
case 1:
if( c == '\n' )
state = 2;
else {
md_putc(md, '\r');
state = 0;
goto again;
}
break;
case 2:
md_putc(md, '\r');
md_putc(md, '\n');
state = 0;
goto again;
default: BUG();
}
iobuf_put( out, c );
lastlf = c == '\n';
}
if( state == 1 )
md_putc(md, '\r');
else if( state == 2 ) { /* file ended with a new line */
md_putc(md, '\r');
md_putc(md, '\n');
iobuf_put( out, '\n');
}
if( !lastlf )
iobuf_put( out, '\n' );
return 0; /* fixme: add error handling */
}
/****************
* make a clear signature. note that opt.armor is not needed
*/
int
clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
{
armor_filter_context_t afx;
text_filter_context_t tfx;
MD_HANDLE textmd = NULL;
IOBUF inp = NULL, out = NULL;
PACKET pkt;
int rc = 0;
SK_LIST sk_list = NULL;
SK_LIST sk_rover = NULL;
int old_style = opt.rfc1991;
int only_md5 = 0;
memset( &afx, 0, sizeof afx);
memset( &tfx, 0, sizeof tfx);
init_packet( &pkt );
if( (rc=build_sk_list( locusr, &sk_list, 1, PUBKEY_USAGE_SIG )) )
goto leave;
if( !old_style )
old_style = only_old_style( sk_list );
/* prepare iobufs */
if( !(inp = iobuf_open(fname)) ) {
log_error("can't open %s: %s\n", fname? fname: "[stdin]",
strerror(errno) );
rc = G10ERR_OPEN_FILE;
goto leave;
}
if( outfile ) {
if( !(out = iobuf_create( outfile )) ) {
log_error(_("can't create %s: %s\n"), outfile, strerror(errno) );
rc = G10ERR_CREATE_FILE;
goto leave;
}
else if( opt.verbose )
log_info(_("writing to '%s'\n"), outfile );
}
else if( (rc = open_outfile( fname, 1, &out )) )
goto leave;
iobuf_writestr(out, "-----BEGIN PGP SIGNED MESSAGE-----\n" );
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
PKT_secret_key *sk = sk_rover->sk;
if( hash_for(sk->pubkey_algo) == DIGEST_ALGO_MD5 )
only_md5 = 1;
else {
only_md5 = 0;
break;
}
}
if( old_style || only_md5 )
iobuf_writestr(out, "\n" );
else {
const char *s;
int any = 0;
iobuf_writestr(out, "Hash: " );
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
PKT_secret_key *sk = sk_rover->sk;
s = digest_algo_to_string( hash_for(sk->pubkey_algo) );
if( s ) {
if( any )
iobuf_put(out, ',' );
iobuf_writestr(out, s );
any = 1;
}
}
assert(any);
iobuf_writestr(out, "\n" );
if( opt.not_dash_escaped )
iobuf_writestr( out,
"NotDashEscaped: You need GnuPG to verify this message\n" );
iobuf_writestr(out, "\n" );
}
textmd = md_open(0, 0);
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
PKT_secret_key *sk = sk_rover->sk;
md_enable(textmd, hash_for(sk->pubkey_algo));
}
md_start_debug( textmd, "create" );
if( !opt.not_dash_escaped )
iobuf_push_filter( inp, text_filter, &tfx );
rc = write_dash_escaped( inp, out, textmd );
if( rc )
goto leave;
afx.what = 2;
iobuf_push_filter( out, armor_filter, &afx );
/* loop over the secret certificates */
for( sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) {
PKT_secret_key *sk;
PKT_signature *sig;
MD_HANDLE md;
sk = sk_rover->sk;
/* build the signature packet */
/* fixme: this code is duplicated above */
sig = m_alloc_clear( sizeof *sig );
sig->version = old_style || opt.force_v3_sigs ? 3 : sk->version;
keyid_from_sk( sk, sig->keyid );
sig->digest_algo = hash_for(sk->pubkey_algo);
sig->pubkey_algo = sk->pubkey_algo;
sig->timestamp = make_timestamp();
sig->sig_class = 0x01;
md = md_copy( textmd );
if( sig->version >= 4 ) {
build_sig_subpkt_from_sig( sig );
md_putc( md, sig->version );
}
md_putc( md, sig->sig_class );
if( sig->version < 4 ) {
u32 a = sig->timestamp;
md_putc( md, (a >> 24) & 0xff );
md_putc( md, (a >> 16) & 0xff );
md_putc( md, (a >> 8) & 0xff );
md_putc( md, a & 0xff );
}
else {
byte buf[6];
size_t n;
md_putc( md, sig->pubkey_algo );
md_putc( md, sig->digest_algo );
if( sig->hashed_data ) {
n = (sig->hashed_data[0] << 8) | sig->hashed_data[1];
md_write( md, sig->hashed_data, n+2 );
n += 6;
}
else
n = 6;
/* add some magic */
buf[0] = sig->version;
buf[1] = 0xff;
buf[2] = n >> 24; /* hmmm, n is only 16 bit, so this is always 0 */
buf[3] = n >> 16;
buf[4] = n >> 8;
buf[5] = n;
md_write( md, buf, 6 );
}
md_final( md );
rc = do_sign( sk, sig, md, hash_for(sig->pubkey_algo) );
md_close( md );
if( !rc ) { /* and write it */
init_packet(&pkt);
pkt.pkttype = PKT_SIGNATURE;
pkt.pkt.signature = sig;
rc = build_packet( out, &pkt );
free_packet( &pkt );
if( rc )
log_error("build signature packet failed: %s\n", g10_errstr(rc) );
}
if( rc )
goto leave;
}
leave:
if( rc )
iobuf_cancel(out);
else
iobuf_close(out);
iobuf_close(inp);
md_close( textmd );
release_sk_list( sk_list );
return rc;
}
/****************
* Create a signature packet for the given public key certificate
* and the user id and return it in ret_sig. User signature class SIGCLASS
* user-id is not used (and may be NULL if sigclass is 0x20)
* If digest_algo is 0 the function selects an appropriate one.
*/
int
make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
PKT_user_id *uid, PKT_public_key *subpk,
PKT_secret_key *sk,
int sigclass, int digest_algo,
int (*mksubpkt)(PKT_signature *, void *), void *opaque
)
{
PKT_signature *sig;
int rc=0;
MD_HANDLE md;
assert( (sigclass >= 0x10 && sigclass <= 0x13)
|| sigclass == 0x20 || sigclass == 0x18 );
if( !digest_algo ) {
switch( sk->pubkey_algo ) {
case PUBKEY_ALGO_DSA: digest_algo = DIGEST_ALGO_SHA1; break;
case PUBKEY_ALGO_RSA_S:
case PUBKEY_ALGO_RSA: digest_algo = DIGEST_ALGO_MD5; break;
default: digest_algo = DIGEST_ALGO_RMD160; break;
}
}
md = md_open( digest_algo, 0 );
/* hash the public key certificate and the user id */
hash_public_key( md, pk );
if( sigclass == 0x18 ) { /* subkey binding */
hash_public_key( md, subpk );
}
else if( sigclass != 0x20 ) {
if( sk->version >=4 ) {
byte buf[5];
buf[0] = 0xb4; /* indicates a userid packet */
buf[1] = uid->len >> 24; /* always use 4 length bytes */
buf[2] = uid->len >> 16;
buf[3] = uid->len >> 8;
buf[4] = uid->len;
md_write( md, buf, 5 );
}
md_write( md, uid->name, uid->len );
}
/* and make the signature packet */
sig = m_alloc_clear( sizeof *sig );
sig->version = sk->version;
keyid_from_sk( sk, sig->keyid );
sig->pubkey_algo = sk->pubkey_algo;
sig->digest_algo = digest_algo;
sig->timestamp = make_timestamp();
sig->sig_class = sigclass;
if( sig->version >= 4 )
build_sig_subpkt_from_sig( sig );
if( sig->version >= 4 && mksubpkt )
rc = (*mksubpkt)( sig, opaque );
if( !rc ) {
if( sig->version >= 4 )
md_putc( md, sig->version );
md_putc( md, sig->sig_class );
if( sig->version < 4 ) {
u32 a = sig->timestamp;
md_putc( md, (a >> 24) & 0xff );
md_putc( md, (a >> 16) & 0xff );
md_putc( md, (a >> 8) & 0xff );
md_putc( md, a & 0xff );
}
else {
byte buf[6];
size_t n;
md_putc( md, sig->pubkey_algo );
md_putc( md, sig->digest_algo );
if( sig->hashed_data ) {
n = (sig->hashed_data[0] << 8) | sig->hashed_data[1];
md_write( md, sig->hashed_data, n+2 );
n += 6;
}
else
n = 6;
/* add some magic */
buf[0] = sig->version;
buf[1] = 0xff;
buf[2] = n >> 24; /* hmmm, n is only 16 bit, so this is always 0 */
buf[3] = n >> 16;
buf[4] = n >> 8;
buf[5] = n;
md_write( md, buf, 6 );
}
md_final(md);
rc = complete_sig( sig, sk, md );
}
md_close( md );
if( rc )
free_seckey_enc( sig );
else
*ret_sig = sig;
return rc;
}
diff --git a/g10/signal.c b/g10/signal.c
index 8a0f3feee..1f599d9d0 100644
--- a/g10/signal.c
+++ b/g10/signal.c
@@ -1,162 +1,162 @@
/* signal.c - signal handling
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <signal.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include "options.h"
#include "errors.h"
#include "memory.h"
#include "util.h"
#include "main.h"
#include "ttyio.h"
static volatile int caught_fatal_sig = 0;
static volatile int caught_sigusr1 = 0;
static const char *
signal_name( int signum )
{
#if SYS_SIGLIST_DECLARED
return sys_siglist[signum];
#else
static char buf[20];
sprintf(buf, "signal %d", signum );
return buf;
#endif
}
static RETSIGTYPE
got_fatal_signal( int sig )
{
if( caught_fatal_sig )
raise( sig );
caught_fatal_sig = 1;
fprintf( stderr, "\n%s: %s caught ... exiting\n",
log_get_name(), signal_name(sig) );
secmem_term();
exit( 8 );
}
static RETSIGTYPE
got_usr_signal( int sig )
{
caught_sigusr1 = 1;
}
#ifndef __MINGW32__
static void
do_sigaction( int sig, struct sigaction *nact )
{
struct sigaction oact;
sigaction( sig, NULL, &oact );
if( oact.sa_handler != SIG_IGN )
sigaction( sig, nact, NULL);
}
#endif
void
init_signals()
{
#ifndef __MINGW32__
struct sigaction nact;
nact.sa_handler = got_fatal_signal;
sigemptyset( &nact.sa_mask );
nact.sa_flags = 0;
do_sigaction( SIGINT, &nact );
do_sigaction( SIGHUP, &nact );
do_sigaction( SIGTERM, &nact );
do_sigaction( SIGQUIT, &nact );
do_sigaction( SIGSEGV, &nact );
nact.sa_handler = got_usr_signal;
sigaction( SIGUSR1, &nact, NULL );
#endif
}
void
pause_on_sigusr( int which )
{
#ifndef __MINGW32__
sigset_t mask, oldmask;
assert( which == 1 );
sigemptyset( &mask );
sigaddset( &mask, SIGUSR1 );
sigprocmask( SIG_BLOCK, &mask, &oldmask );
while( !caught_sigusr1 )
sigsuspend( &oldmask );
caught_sigusr1 = 0;
sigprocmask( SIG_UNBLOCK, &mask, NULL );
#endif
}
static void
do_block( int block )
{
#ifndef __MINGW32__
static int is_blocked;
static sigset_t oldmask;
if( block ) {
sigset_t newmask;
if( is_blocked )
log_bug("signals are already blocked\n");
sigfillset( &newmask );
sigprocmask( SIG_BLOCK, &newmask, &oldmask );
is_blocked = 1;
}
else {
if( !is_blocked )
log_bug("signals are not blocked\n");
sigprocmask( SIG_SETMASK, &oldmask, NULL );
is_blocked = 0;
}
#endif /*__MINGW32__*/
}
void
block_all_signals()
{
do_block(1);
}
void
unblock_all_signals()
{
do_block(0);
}
diff --git a/g10/skclist.c b/g10/skclist.c
index caaab207c..baf4a5cf3 100644
--- a/g10/skclist.c
+++ b/g10/skclist.c
@@ -1,132 +1,132 @@
/* skclist.c
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "options.h"
#include "packet.h"
#include "errors.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "i18n.h"
void
release_sk_list( SK_LIST sk_list )
{
SK_LIST sk_rover;
for( ; sk_list; sk_list = sk_rover ) {
sk_rover = sk_list->next;
free_secret_key( sk_list->sk );
m_free( sk_list );
}
}
int
build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list, int unlock,
unsigned usage )
{
SK_LIST sk_list = NULL;
int rc;
if( !locusr ) { /* use the default one */
PKT_secret_key *sk;
sk = m_alloc_clear( sizeof *sk );
sk->pubkey_usage = usage;
if( (rc = get_seckey_byname( sk, NULL, unlock )) ) {
free_secret_key( sk ); sk = NULL;
log_error("no default secret key: %s\n", g10_errstr(rc) );
}
else if( !(rc=check_pubkey_algo2(sk->pubkey_algo, usage)) ) {
SK_LIST r;
if( sk->version == 4 && (usage & PUBKEY_USAGE_SIG)
&& sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) {
log_error("this is a PGP generated "
"ElGamal key which is NOT secure for signatures!\n");
free_secret_key( sk ); sk = NULL;
}
else {
r = m_alloc( sizeof *r );
r->sk = sk; sk = NULL;
r->next = sk_list;
r->mark = 0;
sk_list = r;
}
}
else {
free_secret_key( sk ); sk = NULL;
log_error("invalid default secret key: %s\n", g10_errstr(rc) );
}
}
else {
for(; locusr; locusr = locusr->next ) {
PKT_secret_key *sk;
sk = m_alloc_clear( sizeof *sk );
sk->pubkey_usage = usage;
if( (rc = get_seckey_byname( sk, locusr->d, unlock )) ) {
free_secret_key( sk ); sk = NULL;
log_error(_("skipped '%s': %s\n"), locusr->d, g10_errstr(rc) );
}
else if( !(rc=check_pubkey_algo2(sk->pubkey_algo, usage)) ) {
SK_LIST r;
if( sk->version == 4 && (usage & PUBKEY_USAGE_SIG)
&& sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E ) {
log_info(_("skipped '%s': this is a PGP generated "
"ElGamal key which is not secure for signatures!\n"),
locusr->d );
free_secret_key( sk ); sk = NULL;
}
else {
r = m_alloc( sizeof *r );
r->sk = sk; sk = NULL;
r->next = sk_list;
r->mark = 0;
sk_list = r;
}
}
else {
free_secret_key( sk ); sk = NULL;
log_error("skipped '%s': %s\n", locusr->d, g10_errstr(rc) );
}
}
}
if( !rc && !sk_list ) {
log_error("no valid signators\n");
rc = G10ERR_NO_USER_ID;
}
if( rc )
release_sk_list( sk_list );
else
*ret_sk_list = sk_list;
return rc;
}
diff --git a/g10/status.c b/g10/status.c
index e441d5e21..71a4e8341 100644
--- a/g10/status.c
+++ b/g10/status.c
@@ -1,340 +1,340 @@
/* status.c
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <unistd.h>
#ifdef USE_SHM_COPROCESSING
#ifdef HAVE_SYS_IPC_H
#include <sys/ipc.h>
#endif
#ifdef HAVE_SYS_SHM_H
#include <sys/shm.h>
#endif
#if defined(HAVE_MLOCK)
#include <sys/mman.h>
#endif
#endif
#include "util.h"
#include "status.h"
#include "ttyio.h"
#include "options.h"
#include "main.h"
#include "i18n.h"
static int fd = -1;
#ifdef USE_SHM_COPROCESSING
static int shm_id = -1;
static volatile char *shm_area;
static size_t shm_size;
static int shm_is_locked;
#endif /*USE_SHM_COPROCESSING*/
void
set_status_fd ( int newfd )
{
fd = newfd;
}
void
write_status ( int no )
{
write_status_text( no, NULL );
}
void
write_status_text ( int no, const char *text)
{
const char *s;
if( fd == -1 )
return; /* not enabled */
switch( no ) {
case STATUS_ENTER : s = "ENTER\n"; break;
case STATUS_LEAVE : s = "LEAVE\n"; break;
case STATUS_ABORT : s = "ABORT\n"; break;
case STATUS_GOODSIG: s = "GOODSIG\n"; break;
case STATUS_SIGEXPIRED: s = "SIGEXPIRED\n"; break;
case STATUS_KEYREVOKED: s = "KEYREVOKED\n"; break;
case STATUS_BADSIG : s = "BADSIG\n"; break;
case STATUS_ERRSIG : s = "ERRSIG\n"; break;
case STATUS_BADARMOR : s = "BADARMOR\n"; break;
case STATUS_RSA_OR_IDEA : s= "RSA_OR_IDEA\n"; break;
case STATUS_TRUST_UNDEFINED: s = "TRUST_UNDEFINED\n"; break;
case STATUS_TRUST_NEVER : s = "TRUST_NEVER\n"; break;
case STATUS_TRUST_MARGINAL : s = "TRUST_MARGINAL\n"; break;
case STATUS_TRUST_FULLY : s = "TRUST_FULLY\n"; break;
case STATUS_TRUST_ULTIMATE : s = "TRUST_ULTIMATE\n"; break;
case STATUS_SHM_INFO : s = "SHM_INFO\n"; break;
case STATUS_SHM_GET : s = "SHM_GET\n"; break;
case STATUS_SHM_GET_BOOL : s = "SHM_GET_BOOL\n"; break;
case STATUS_SHM_GET_HIDDEN : s = "SHM_GET_HIDDEN\n"; break;
case STATUS_NEED_PASSPHRASE: s = "NEED_PASSPHRASE\n"; break;
default: s = "?\n"; break;
}
write( fd, "[GNUPG:] ", 9 );
if( text ) {
write( fd, s, strlen(s)-1 );
write( fd, " ", 1 );
write( fd, text, strlen(text) );
write( fd, "\n", 1 );
}
else
write( fd, s, strlen(s) );
}
#ifdef USE_SHM_COPROCESSING
#ifndef IPC_RMID_DEFERRED_RELEASE
static void
remove_shmid( void )
{
if( shm_id != -1 ) {
shmctl ( shm_id, IPC_RMID, 0);
shm_id = -1;
}
}
#endif
void
init_shm_coprocessing ( ulong requested_shm_size, int lock_mem )
{
char buf[100];
struct shmid_ds shmds;
#ifndef IPC_RMID_DEFERRED_RELEASE
atexit( remove_shmid );
#endif
requested_shm_size = (requested_shm_size + 4095) & ~4095;
if ( requested_shm_size > 2 * 4096 )
log_fatal("too much shared memory requested; only 8k are allowed\n");
shm_size = 4096 /* one page for us */ + requested_shm_size;
shm_id = shmget( IPC_PRIVATE, shm_size, IPC_CREAT | 0700 );
if ( shm_id == -1 )
log_fatal("can't get %uk of shared memory: %s\n",
(unsigned)shm_size/1024, strerror(errno));
shm_area = shmat( shm_id, 0, 0 );
if ( shm_area == (char*)-1 )
log_fatal("can't attach %uk shared memory: %s\n",
(unsigned)shm_size/1024, strerror(errno));
log_debug("mapped %uk shared memory at %p, id=%d\n",
(unsigned)shm_size/1024, shm_area, shm_id );
if( lock_mem ) {
#ifdef IPC_HAVE_SHM_LOCK
if ( shmctl (shm_id, SHM_LOCK, 0) )
log_info("locking shared memory %d failed: %s\n",
shm_id, strerror(errno));
else
shm_is_locked = 1;
#elif defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
/* (need the cast for Solaris with Sun's workshop compilers) */
if ( mlock ( (char*)shm_area, shm_size) )
log_info("locking shared memory %d failed: %s\n",
shm_id, strerror(errno));
else
shm_is_locked = 1;
#else
log_info("Locking shared memory %d failed: No way to do it\n", shm_id );
#endif
}
#ifdef IPC_RMID_DEFERRED_RELEASE
if( shmctl( shm_id, IPC_RMID, 0) )
log_fatal("shmctl IPC_RMDID of %d failed: %s\n",
shm_id, strerror(errno));
#endif
if( shmctl( shm_id, IPC_STAT, &shmds ) )
log_fatal("shmctl IPC_STAT of %d failed: %s\n",
shm_id, strerror(errno));
if( shmds.shm_perm.uid != getuid() ) {
shmds.shm_perm.uid = getuid();
if( shmctl( shm_id, IPC_SET, &shmds ) )
log_fatal("shmctl IPC_SET of %d failed: %s\n",
shm_id, strerror(errno));
}
/* write info; Protocol version, id, size, locked size */
sprintf( buf, "pv=1 pid=%d shmid=%d sz=%u lz=%u", (int)getpid(),
shm_id, (unsigned)shm_size, shm_is_locked? (unsigned)shm_size:0 );
write_status_text( STATUS_SHM_INFO, buf );
}
/****************
* Request a string from client
* If bool, returns static string on true (do not free) or NULL for false
*/
static char *
do_shm_get( const char *keyword, int hidden, int bool )
{
size_t n;
byte *p;
char *string;
if( !shm_area )
BUG();
shm_area[0] = 0; /* msb of length of control block */
shm_area[1] = 32; /* and lsb */
shm_area[2] = 1; /* indicate that we are waiting on a reply */
shm_area[3] = 0; /* clear data available flag */
write_status_text( bool? STATUS_SHM_GET_BOOL :
hidden? STATUS_SHM_GET_HIDDEN : STATUS_SHM_GET, keyword );
do {
pause_on_sigusr(1);
if( shm_area[0] || shm_area[1] != 32 || shm_area[2] != 1 )
log_fatal("client modified shm control block - abort\n");
} while( !shm_area[3] );
shm_area[2] = 0; /* reset request flag */
p = (byte*)shm_area+32;
n = p[0] << 8 | p[1];
p += 2;
if( n+32+2+1 > 4095 )
log_fatal("client returns too large data (%u bytes)\n", (unsigned)n );
if( bool )
return p[0]? "" : NULL;
string = hidden? m_alloc_secure( n+1 ) : m_alloc( n+1 );
memcpy(string, p, n );
string[n] = 0; /* make sure it is a string */
if( hidden ) /* invalidate the memory */
memset( p, 0, n );
return string;
}
#endif /* USE_SHM_COPROCESSING */
int
cpr_enabled()
{
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return 1;
#endif
return 0;
}
char *
cpr_get( const char *keyword, const char *prompt )
{
char *p;
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return do_shm_get( keyword, 0, 0 );
#endif
for(;;) {
p = tty_get( prompt );
if( *p == '?' && !p[1] ) {
m_free(p);
display_online_help( keyword );
}
else
return p;
}
}
char *
cpr_get_utf8( const char *keyword, const char *prompt )
{
char *p;
p = cpr_get( keyword, prompt );
if( p ) {
char *utf8 = native_to_utf8( p );
m_free( p );
p = utf8;
}
return p;
}
char *
cpr_get_hidden( const char *keyword, const char *prompt )
{
char *p;
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return do_shm_get( keyword, 1, 0 );
#endif
for(;;) {
p = tty_get_hidden( prompt );
if( *p == '?' && !p[1] ) {
m_free(p);
display_online_help( keyword );
}
else
return p;
}
}
void
cpr_kill_prompt(void)
{
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return;
#endif
tty_kill_prompt();
return;
}
int
cpr_get_answer_is_yes( const char *keyword, const char *prompt )
{
int yes;
char *p;
#ifdef USE_SHM_COPROCESSING
if( opt.shm_coprocess )
return !!do_shm_get( keyword, 0, 1 );
#endif
for(;;) {
p = tty_get( prompt );
trim_spaces(p); /* it is okay to do this here */
if( *p == '?' && !p[1] ) {
m_free(p);
display_online_help( keyword );
}
else {
tty_kill_prompt();
yes = answer_is_yes(p);
m_free(p);
return yes;
}
}
}
diff --git a/g10/status.h b/g10/status.h
index 4adce1282..fa1583687 100644
--- a/g10/status.h
+++ b/g10/status.h
@@ -1,69 +1,69 @@
/* status.h
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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_STATUS_H
#define G10_STATUS_H
#define STATUS_ENTER 1
#define STATUS_LEAVE 2
#define STATUS_ABORT 3
#define STATUS_GOODSIG 4
#define STATUS_BADSIG 5
#define STATUS_ERRSIG 6
#define STATUS_BADARMOR 7
#define STATUS_RSA_OR_IDEA 8
#define STATUS_SIGEXPIRED 9
#define STATUS_KEYREVOKED 10
#define STATUS_TRUST_UNDEFINED 11
#define STATUS_TRUST_NEVER 12
#define STATUS_TRUST_MARGINAL 13
#define STATUS_TRUST_FULLY 14
#define STATUS_TRUST_ULTIMATE 15
#define STATUS_SHM_INFO 16
#define STATUS_SHM_GET 17
#define STATUS_SHM_GET_BOOL 18
#define STATUS_SHM_GET_HIDDEN 19
#define STATUS_NEED_PASSPHRASE 20
/*-- status.c --*/
void set_status_fd ( int fd );
void write_status ( int no );
void write_status_text ( int no, const char *text );
#ifdef USE_SHM_COPROCESSING
void init_shm_coprocessing ( ulong requested_shm_size, int lock_mem );
#endif /*USE_SHM_COPROCESSING*/
int cpr_enabled(void);
char *cpr_get( const char *keyword, const char *prompt );
char *cpr_get_utf8( const char *keyword, const char *prompt );
char *cpr_get_hidden( const char *keyword, const char *prompt );
void cpr_kill_prompt(void);
int cpr_get_answer_is_yes( const char *keyword, const char *prompt );
#endif /*G10_STATUS_H*/
diff --git a/g10/tdbio.c b/g10/tdbio.c
index 5d1864c3d..f7ba36f7c 100644
--- a/g10/tdbio.c
+++ b/g10/tdbio.c
@@ -1,1533 +1,1533 @@
/* tdbio.c
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "errors.h"
#include "iobuf.h"
#include "memory.h"
#include "util.h"
#include "options.h"
#include "main.h"
#include "i18n.h"
#include "trustdb.h"
#include "tdbio.h"
/****************
* Yes, this is a very simple implementation. We should really
* use a page aligned buffer and read complete pages.
* To implement a simple trannsaction system, this is sufficient.
*/
typedef struct cache_ctrl_struct *CACHE_CTRL;
struct cache_ctrl_struct {
CACHE_CTRL next;
struct {
unsigned used:1;
unsigned dirty:1;
} flags;
ulong recno;
char data[TRUST_RECORD_LEN];
};
#define MAX_CACHE_ENTRIES_SOFT 200 /* may be increased while in a */
#define MAX_CACHE_ENTRIES_HARD 1000 /* transaction to this one */
static CACHE_CTRL cache_list;
static int cache_entries;
static int cache_is_dirty;
/* a type used to pass infomation to cmp_krec_fpr */
struct cmp_krec_fpr_struct {
int pubkey_algo;
const char *fpr;
int fprlen;
};
/* a type used to pass infomation to cmp_sdir */
struct cmp_sdir_struct {
int pubkey_algo;
u32 keyid[2];
};
static char *db_name;
static const char *lockname;
static int db_fd = -1;
static int in_transaction;
static void open_db(void);
/*************************************
************* record cache **********
*************************************/
/****************
* Get the data from therecord cache and return a
* pointer into that cache. Caller should copy
* the return data. NULL is returned on a cache miss.
*/
static const char *
get_record_from_cache( ulong recno )
{
CACHE_CTRL r;
for( r = cache_list; r; r = r->next ) {
if( r->flags.used && r->recno == recno )
return r->data;
}
return NULL;
}
static int
write_cache_item( CACHE_CTRL r )
{
int n;
if( lseek( db_fd, r->recno * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
log_error(_("trustdb rec %lu: lseek failed: %s\n"),
r->recno, strerror(errno) );
return G10ERR_WRITE_FILE;
}
n = write( db_fd, r->data, TRUST_RECORD_LEN);
if( n != TRUST_RECORD_LEN ) {
log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"),
r->recno, n, strerror(errno) );
return G10ERR_WRITE_FILE;
}
r->flags.dirty = 0;
return 0;
}
/****************
* Put data into the cache. This function may flush the
* some cache entries if there is not enough space available.
*/
int
put_record_into_cache( ulong recno, const char *data )
{
CACHE_CTRL r, unused;
int dirty_count = 0;
int clean_count = 0;
/* see whether we already cached this one */
for( unused = NULL, r = cache_list; r; r = r->next ) {
if( !r->flags.used ) {
if( !unused )
unused = r;
}
else if( r->recno == recno ) {
if( !r->flags.dirty ) {
/* Hmmm: should we use a a copy and compare? */
if( memcmp(r->data, data, TRUST_RECORD_LEN ) ) {
r->flags.dirty = 1;
cache_is_dirty = 1;
}
}
memcpy( r->data, data, TRUST_RECORD_LEN );
return 0;
}
if( r->flags.used ) {
if( r->flags.dirty )
dirty_count++;
else
clean_count++;
}
}
/* not in the cache: add a new entry */
if( unused ) { /* reuse this entry */
r = unused;
r->flags.used = 1;
r->recno = recno;
memcpy( r->data, data, TRUST_RECORD_LEN );
r->flags.dirty = 1;
cache_is_dirty = 1;
cache_entries++;
return 0;
}
/* see whether we reached the limit */
if( cache_entries < MAX_CACHE_ENTRIES_SOFT ) { /* no */
r = m_alloc( sizeof *r );
r->flags.used = 1;
r->recno = recno;
memcpy( r->data, data, TRUST_RECORD_LEN );
r->flags.dirty = 1;
r->next = cache_list;
cache_list = r;
cache_is_dirty = 1;
cache_entries++;
return 0;
}
/* cache is full: discard some clean entries */
if( clean_count ) {
int n = clean_count / 3; /* discard a third of the clean entries */
if( !n )
n = 1;
for( unused = NULL, r = cache_list; r; r = r->next ) {
if( r->flags.used && !r->flags.dirty ) {
if( !unused )
unused = r;
r->flags.used = 0;
cache_entries--;
if( !--n )
break;
}
}
assert( unused );
r = unused;
r->flags.used = 1;
r->recno = recno;
memcpy( r->data, data, TRUST_RECORD_LEN );
r->flags.dirty = 1;
cache_is_dirty = 1;
cache_entries++;
return 0;
}
/* no clean entries: have to flush some dirty entries */
if( in_transaction ) {
/* but we can't do this while in a transaction
* we increase the cache size instead */
if( cache_entries < MAX_CACHE_ENTRIES_HARD ) { /* no */
if( opt.debug && !(cache_entries % 100) )
log_debug("increasing tdbio cache size\n");
r = m_alloc( sizeof *r );
r->flags.used = 1;
r->recno = recno;
memcpy( r->data, data, TRUST_RECORD_LEN );
r->flags.dirty = 1;
r->next = cache_list;
cache_list = r;
cache_is_dirty = 1;
cache_entries++;
return 0;
}
log_info(_("trustdb transaction to large\n"));
return G10ERR_RESOURCE_LIMIT;
}
if( dirty_count ) {
int n = dirty_count / 5; /* discard some dirty entries */
if( !n )
n = 1;
if( !lockname )
lockname = make_dotlock( db_name, -1 );
if( !lockname )
log_fatal("can't get a lock - giving up\n");
for( unused = NULL, r = cache_list; r; r = r->next ) {
if( r->flags.used && r->flags.dirty ) {
int rc = write_cache_item( r );
if( rc )
return rc;
if( !unused )
unused = r;
r->flags.used = 0;
cache_entries--;
if( !--n )
break;
}
}
if( !opt.lock_once ) {
release_dotlock( lockname );
lockname=NULL;
}
assert( unused );
r = unused;
r->flags.used = 1;
r->recno = recno;
memcpy( r->data, data, TRUST_RECORD_LEN );
r->flags.dirty = 1;
cache_is_dirty = 1;
cache_entries++;
return 0;
}
BUG();
}
int
tdbio_is_dirty()
{
return cache_is_dirty;
}
/****************
* Flush the cache. This cannot be used while in a transaction.
*/
int
tdbio_sync()
{
CACHE_CTRL r;
int did_lock = 0;
if( in_transaction )
log_bug("tdbio: syncing while in transaction\n");
if( !cache_is_dirty )
return 0;
if( !lockname ) {
lockname = make_dotlock( db_name, -1 );
did_lock = 1;
if( !lockname )
log_fatal("can't get a lock - giving up\n");
}
for( r = cache_list; r; r = r->next ) {
if( r->flags.used && r->flags.dirty ) {
int rc = write_cache_item( r );
if( rc )
return rc;
}
}
cache_is_dirty = 0;
if( did_lock && !opt.lock_once ) {
release_dotlock( lockname );
lockname=NULL;
}
return 0;
}
/****************
* Simple transactions system:
* Everything between begin_transaction and end/cancel_transaction
* is not immediatly written but at the time of end_transaction.
*
*/
int
tdbio_begin_transaction()
{
int rc;
if( in_transaction )
log_bug("tdbio: nested transactions\n");
/* flush everything out */
rc = tdbio_sync();
if( rc )
return rc;
in_transaction = 1;
return 0;
}
int
tdbio_end_transaction()
{
int rc;
if( !in_transaction )
log_bug("tdbio: no active transaction\n");
if( !lockname )
lockname = make_dotlock( db_name, -1 );
if( !lockname )
log_fatal("can't get a lock - giving up\n");
block_all_signals();
in_transaction = 0;
rc = tdbio_sync();
unblock_all_signals();
if( !opt.lock_once ) {
release_dotlock( lockname );
lockname=NULL;
}
return rc;
}
int
tdbio_cancel_transaction()
{
CACHE_CTRL r;
if( !in_transaction )
log_bug("tdbio: no active transaction\n");
/* remove all dirty marked entries, so that the original ones
* are read back the next time */
if( cache_is_dirty ) {
for( r = cache_list; r; r = r->next ) {
if( r->flags.used && r->flags.dirty ) {
r->flags.used = 0;
cache_entries--;
}
}
cache_is_dirty = 0;
}
in_transaction = 0;
return 0;
}
/********************************************************
**************** cached I/O functions ******************
********************************************************/
int
tdbio_set_dbname( const char *new_dbname, int create )
{
char *fname;
fname = new_dbname? m_strdup( new_dbname )
: make_filename(opt.homedir, "trustdb.gpg", NULL );
if( access( fname, R_OK ) ) {
if( errno != ENOENT ) {
log_error( _("%s: can't access: %s\n"), fname, strerror(errno) );
m_free(fname);
return G10ERR_TRUSTDB;
}
if( create ) {
FILE *fp;
TRUSTREC rec;
int rc;
char *p = strrchr( fname, '/' );
assert(p);
*p = 0;
if( access( fname, F_OK ) ) {
if( strlen(fname) >= 7
&& !strcmp(fname+strlen(fname)-7, "/.gnupg" ) ) {
#if __MINGW32__
if( mkdir( fname ) )
#else
if( mkdir( fname, S_IRUSR|S_IWUSR|S_IXUSR ) )
#endif
log_fatal( _("%s: can't create directory: %s\n"),
fname, strerror(errno) );
else
log_info( _("%s: directory created\n"), fname );
copy_options_file( fname );
}
else
log_fatal( _("%s: directory does not exist!\n"), fname );
}
*p = '/';
fp =fopen( fname, "wb" );
if( !fp )
log_fatal( _("%s: can't create: %s\n"), fname, strerror(errno) );
fclose(fp);
m_free(db_name);
db_name = fname;
#ifdef __MINGW32__
db_fd = open( db_name, O_RDWR | O_BINARY );
#else
db_fd = open( db_name, O_RDWR );
#endif
if( db_fd == -1 )
log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) );
memset( &rec, 0, sizeof rec );
rec.r.ver.version = 2;
rec.r.ver.created = make_timestamp();
rec.r.ver.marginals = opt.marginals_needed;
rec.r.ver.completes = opt.completes_needed;
rec.r.ver.cert_depth = opt.max_cert_depth;
rec.rectype = RECTYPE_VER;
rec.recnum = 0;
rc = tdbio_write_record( &rec );
if( !rc )
tdbio_sync();
if( rc )
log_fatal( _("%s: failed to create version record: %s"),
fname, g10_errstr(rc));
/* and read again to check that we are okay */
if( tdbio_read_record( 0, &rec, RECTYPE_VER ) )
log_fatal( _("%s: invalid trust-db created\n"), db_name );
log_info(_("%s: trust-db created\n"), db_name);
return 0;
}
}
m_free(db_name);
db_name = fname;
return 0;
}
const char *
tdbio_get_dbname()
{
return db_name;
}
static void
cleanup(void)
{
if( lockname ) {
release_dotlock(lockname);
lockname = NULL;
}
}
static void
open_db()
{
TRUSTREC rec;
assert( db_fd == -1 );
#ifdef __MINGW32__
db_fd = open( db_name, O_RDWR | O_BINARY );
#else
db_fd = open( db_name, O_RDWR );
#endif
if( db_fd == -1 )
log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) );
if( tdbio_read_record( 0, &rec, RECTYPE_VER ) )
log_fatal( _("%s: invalid trust-db\n"), db_name );
atexit( cleanup );
}
/****************
* Make a hashtable: type 0 = key hash, 1 = sdir hash
*/
static void
create_hashtable( TRUSTREC *vr, int type )
{
TRUSTREC rec;
off_t offset;
ulong recnum;
int i, n, rc;
offset = lseek( db_fd, 0, SEEK_END );
if( offset == -1 )
log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) );
recnum = offset / TRUST_RECORD_LEN;
assert(recnum); /* this is will never be the first record */
if( !type )
vr->r.ver.keyhashtbl = recnum;
else
vr->r.ver.sdirhashtbl = recnum;
/* Now write the records */
n = (256+ITEMS_PER_HTBL_RECORD-1) / ITEMS_PER_HTBL_RECORD;
for(i=0; i < n; i++, recnum++ ) {
memset( &rec, 0, sizeof rec );
rec.rectype = RECTYPE_HTBL;
rec.recnum = recnum;
rc = tdbio_write_record( &rec );
if( rc )
log_fatal( _("%s: failed to create hashtable: %s\n"),
db_name, g10_errstr(rc));
}
/* update the version record */
rc = tdbio_write_record( vr );
if( !rc )
rc = tdbio_sync();
if( rc )
log_fatal( _("%s: error updating version record: %s\n"),
db_name, g10_errstr(rc));
}
int
tdbio_db_matches_options()
{
static int yes_no = -1;
if( yes_no == -1 ) {
TRUSTREC vr;
int rc;
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, g10_errstr(rc) );
if( !vr.r.ver.marginals && !vr.r.ver.completes
&& !vr.r.ver.cert_depth )
{ /* special hack for trustdbs created by old versions of GnuPG */
vr.r.ver.marginals = opt.marginals_needed;
vr.r.ver.completes = opt.completes_needed;
vr.r.ver.cert_depth = opt.max_cert_depth;
rc = tdbio_write_record( &vr );
if( !rc && !in_transaction )
rc = tdbio_sync();
if( rc )
log_error( _("%s: error writing version record: %s\n"),
db_name, g10_errstr(rc) );
}
yes_no = vr.r.ver.marginals == opt.marginals_needed
&& vr.r.ver.completes == opt.completes_needed
&& vr.r.ver.cert_depth == opt.max_cert_depth;
}
return yes_no;
}
/****************
* Return the record number of the keyhash tbl or create a new one.
*/
static ulong
get_keyhashrec()
{
static ulong keyhashtbl; /* record number of the key hashtable */
if( !keyhashtbl ) {
TRUSTREC vr;
int rc;
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, g10_errstr(rc) );
if( !vr.r.ver.keyhashtbl )
create_hashtable( &vr, 0 );
keyhashtbl = vr.r.ver.keyhashtbl;
}
return keyhashtbl;
}
/****************
* Return the record number of the shadow direcory hash table
* or create a new one.
*/
static ulong
get_sdirhashrec()
{
static ulong sdirhashtbl; /* record number of the hashtable */
if( !sdirhashtbl ) {
TRUSTREC vr;
int rc;
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, g10_errstr(rc) );
if( !vr.r.ver.sdirhashtbl )
create_hashtable( &vr, 1 );
sdirhashtbl = vr.r.ver.sdirhashtbl;
}
return sdirhashtbl;
}
/****************
* Update a hashtable.
* table gives the start of the table, key and keylen is the key,
* newrecnum is the record number to insert.
*/
static int
upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
{
TRUSTREC lastrec, rec;
ulong hashrec, item;
int msb;
int level=0;
int rc, i;
hashrec = table;
next_level:
msb = key[level];
hashrec += msb / ITEMS_PER_HTBL_RECORD;
rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL );
if( rc ) {
log_error( db_name, "upd_hashtable: read failed: %s\n",
g10_errstr(rc) );
return rc;
}
item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
if( !item ) { /* insert a new item into the hash table */
rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = newrecnum;
rc = tdbio_write_record( &rec );
if( rc ) {
log_error( db_name, "upd_hashtable: write htbl failed: %s\n",
g10_errstr(rc) );
return rc;
}
}
else if( item != newrecnum ) { /* must do an update */
lastrec = rec;
rc = tdbio_read_record( item, &rec, 0 );
if( rc ) {
log_error( "upd_hashtable: read item failed: %s\n",
g10_errstr(rc) );
return rc;
}
if( rec.rectype == RECTYPE_HTBL ) {
hashrec = item;
level++;
if( level >= keylen ) {
log_error( "hashtable has invalid indirections.\n");
return G10ERR_TRUSTDB;
}
goto next_level;
}
else if( rec.rectype == RECTYPE_HLST ) { /* extend list */
/* see whether the key is already in this list */
for(;;) {
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
if( rec.r.hlst.rnum[i] == newrecnum ) {
return 0; /* okay, already in the list */
}
}
if( rec.r.hlst.next ) {
rc = tdbio_read_record( rec.r.hlst.next,
&rec, RECTYPE_HLST);
if( rc ) {
log_error( "scan keyhashtbl read hlst failed: %s\n",
g10_errstr(rc) );
return rc;
}
}
else
break; /* not there */
}
/* find the next free entry and put it in */
for(;;) {
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
if( !rec.r.hlst.rnum[i] ) {
rec.r.hlst.rnum[i] = newrecnum;
rc = tdbio_write_record( &rec );
if( rc )
log_error( "upd_hashtable: write hlst failed: %s\n",
g10_errstr(rc) );
return rc; /* done */
}
}
if( rec.r.hlst.next ) {
rc = tdbio_read_record( rec.r.hlst.next,
&rec, RECTYPE_HLST );
if( rc ) {
log_error( "upd_hashtable: read hlst failed: %s\n",
g10_errstr(rc) );
return rc;
}
}
else { /* add a new list record */
rec.r.hlst.next = item = tdbio_new_recnum();
rc = tdbio_write_record( &rec );
if( rc ) {
log_error( "upd_hashtable: write hlst failed: %s\n",
g10_errstr(rc) );
return rc;
}
memset( &rec, 0, sizeof rec );
rec.rectype = RECTYPE_HLST;
rec.recnum = item;
rec.r.hlst.rnum[0] = newrecnum;
rc = tdbio_write_record( &rec );
if( rc )
log_error( "upd_hashtable: write ext hlst failed: %s\n",
g10_errstr(rc) );
return rc; /* done */
}
} /* end loop over hlst slots */
}
else if( rec.rectype == RECTYPE_KEY
|| rec.rectype == RECTYPE_DIR
|| rec.rectype == RECTYPE_SDIR ) { /* insert a list record */
if( rec.recnum == newrecnum ) {
return 0;
}
item = rec.recnum; /* save number of key record */
memset( &rec, 0, sizeof rec );
rec.rectype = RECTYPE_HLST;
rec.recnum = tdbio_new_recnum();
rec.r.hlst.rnum[0] = item; /* old keyrecord */
rec.r.hlst.rnum[1] = newrecnum; /* and new one */
rc = tdbio_write_record( &rec );
if( rc ) {
log_error( "upd_hashtable: write new hlst failed: %s\n",
g10_errstr(rc) );
return rc;
}
/* update the hashtable record */
lastrec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = rec.recnum;
rc = tdbio_write_record( &lastrec );
if( rc )
log_error( "upd_hashtable: update htbl failed: %s\n",
g10_errstr(rc) );
return rc; /* ready */
}
else {
log_error( "hashtbl %lu points to an invalid record\n",
item);
return G10ERR_TRUSTDB;
}
}
return 0;
}
/****************
* Lookup a record via the hashtable tablewith key/keylen and return the
* result in rec. cmp() should return if the record is the desired one.
* Returns -1 if not found, 0 if found or another errocode
*/
static int
lookup_hashtable( ulong table, const byte *key, size_t keylen,
int (*cmpfnc)(void*, const TRUSTREC *), void *cmpdata,
TRUSTREC *rec )
{
int rc;
ulong hashrec, item;
int msb;
int level=0;
hashrec = table;
next_level:
msb = key[level];
hashrec += msb / ITEMS_PER_HTBL_RECORD;
rc = tdbio_read_record( hashrec, rec, RECTYPE_HTBL );
if( rc ) {
log_error( db_name, "lookup_hashtable failed: %s\n", g10_errstr(rc) );
return rc;
}
item = rec->r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
if( !item )
return -1; /* not found */
rc = tdbio_read_record( item, rec, 0 );
if( rc ) {
log_error( db_name, "hashtable read failed: %s\n", g10_errstr(rc) );
return rc;
}
if( rec->rectype == RECTYPE_HTBL ) {
hashrec = item;
level++;
if( level >= keylen ) {
log_error( db_name, "hashtable has invalid indirections\n");
return G10ERR_TRUSTDB;
}
goto next_level;
}
else if( rec->rectype == RECTYPE_HLST ) {
for(;;) {
int i;
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
if( rec->r.hlst.rnum[i] ) {
TRUSTREC tmp;
rc = tdbio_read_record( rec->r.hlst.rnum[i], &tmp, 0 );
if( rc ) {
log_error( "lookup_hashtable: read item failed: %s\n",
g10_errstr(rc) );
return rc;
}
if( (*cmpfnc)( cmpdata, &tmp ) ) {
*rec = tmp;
return 0;
}
}
}
if( rec->r.hlst.next ) {
rc = tdbio_read_record( rec->r.hlst.next, rec, RECTYPE_HLST );
if( rc ) {
log_error( "lookup_hashtable: read hlst failed: %s\n",
g10_errstr(rc) );
return rc;
}
}
else
return -1; /* not found */
}
}
if( (*cmpfnc)( cmpdata, rec ) )
return 0; /* really found */
return -1; /* no: not found */
}
/****************
* Update the key hashtbl or create the table if it does not exist
*/
static int
update_keyhashtbl( TRUSTREC *kr )
{
return upd_hashtable( get_keyhashrec(),
kr->r.key.fingerprint,
kr->r.key.fingerprint_len, kr->recnum );
}
/****************
* Update the shadow dir hashtbl or create the table if it does not exist
*/
static int
update_sdirhashtbl( TRUSTREC *sr )
{
byte key[8];
u32tobuf( key , sr->r.sdir.keyid[0] );
u32tobuf( key+4 , sr->r.sdir.keyid[1] );
return upd_hashtable( get_sdirhashrec(), key, 8, sr->recnum );
}
void
tdbio_dump_record( TRUSTREC *rec, FILE *fp )
{
int i;
ulong rnum = rec->recnum;
byte *p;
fprintf(fp, "rec %5lu, ", rnum );
switch( rec->rectype ) {
case 0: fprintf(fp, "blank\n");
break;
case RECTYPE_VER: fprintf(fp,
"version, kd=%lu, sd=%lu, free=%lu, m/c/d=%d/%d/%d\n",
rec->r.ver.keyhashtbl, rec->r.ver.sdirhashtbl,
rec->r.ver.firstfree,
rec->r.ver.marginals,
rec->r.ver.completes,
rec->r.ver.cert_depth );
break;
case RECTYPE_FREE: fprintf(fp, "free, next=%lu\n", rec->r.free.next );
break;
case RECTYPE_DIR:
fprintf(fp, "dir %lu, keys=%lu, uids=%lu, t=%02x",
rec->r.dir.lid,
rec->r.dir.keylist,
rec->r.dir.uidlist,
rec->r.dir.ownertrust );
if( rec->r.dir.dirflags & DIRF_VALVALID )
fprintf( fp, ", v=%02x", rec->r.dir.validity );
if( rec->r.dir.dirflags & DIRF_CHECKED ) {
if( rec->r.dir.dirflags & DIRF_VALID )
fputs(", valid", fp );
if( rec->r.dir.dirflags & DIRF_EXPIRED )
fputs(", expired", fp );
if( rec->r.dir.dirflags & DIRF_REVOKED )
fputs(", revoked", fp );
}
putc('\n', fp);
break;
case RECTYPE_KEY:
fprintf(fp, "key %lu, n=%lu a=%d ",
rec->r.key.lid,
rec->r.key.next,
rec->r.key.pubkey_algo );
for(i=0; i < rec->r.key.fingerprint_len; i++ )
fprintf(fp, "%02X", rec->r.key.fingerprint[i] );
if( rec->r.key.keyflags & KEYF_CHECKED ) {
if( rec->r.key.keyflags & KEYF_VALID )
fputs(", valid", fp );
if( rec->r.key.keyflags & KEYF_EXPIRED )
fputs(", expired", fp );
if( rec->r.key.keyflags & KEYF_REVOKED )
fputs(", revoked", fp );
}
putc('\n', fp);
break;
case RECTYPE_UID:
fprintf(fp, "uid %lu, next=%lu, pref=%lu, sig=%lu, hash=%02X%02X",
rec->r.uid.lid,
rec->r.uid.next,
rec->r.uid.prefrec,
rec->r.uid.siglist,
rec->r.uid.namehash[18], rec->r.uid.namehash[19]);
if( rec->r.uid.uidflags & UIDF_CHECKED ) {
if( rec->r.uid.uidflags & UIDF_VALID )
fputs(", valid", fp );
if( rec->r.uid.uidflags & UIDF_REVOKED )
fputs(", revoked", fp );
}
putc('\n', fp);
break;
case RECTYPE_PREF:
fprintf(fp, "pref %lu, next=%lu,",
rec->r.pref.lid, rec->r.pref.next);
for(i=0,p=rec->r.pref.data; i < ITEMS_PER_PREF_RECORD; i+=2,p+=2 ) {
if( *p )
fprintf(fp, " %c%d", *p == PREFTYPE_SYM ? 'S' :
*p == PREFTYPE_HASH ? 'H' :
*p == PREFTYPE_COMPR ? 'Z' : '?', p[1]);
}
putc('\n', fp);
break;
case RECTYPE_SIG:
fprintf(fp, "sig %lu, next=%lu,",
rec->r.sig.lid, rec->r.sig.next );
for(i=0; i < SIGS_PER_RECORD; i++ ) {
if( rec->r.sig.sig[i].lid ) {
fprintf(fp, " %lu:", rec->r.sig.sig[i].lid );
if( rec->r.sig.sig[i].flag & SIGF_CHECKED ) {
fprintf(fp,"%c%c%c",
(rec->r.sig.sig[i].flag & SIGF_VALID) ? 'V':'-',
(rec->r.sig.sig[i].flag & SIGF_EXPIRED) ? 'E':'-',
(rec->r.sig.sig[i].flag & SIGF_REVOKED) ? 'R':'-');
}
else if( rec->r.sig.sig[i].flag & SIGF_NOPUBKEY)
fputs("?--", fp);
else
fputs("---", fp);
}
}
putc('\n', fp);
break;
case RECTYPE_SDIR:
fprintf(fp, "sdir %lu, keyid=%08lX%08lX, algo=%d, hint=%lu\n",
rec->r.sdir.lid,
(ulong)rec->r.sdir.keyid[0],
(ulong)rec->r.sdir.keyid[1],
rec->r.sdir.pubkey_algo,
(ulong)rec->r.sdir.hintlist );
break;
case RECTYPE_CACH:
fprintf(fp, "cach\n");
break;
case RECTYPE_HTBL:
fprintf(fp, "htbl,");
for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ )
fprintf(fp, " %lu", rec->r.htbl.item[i] );
putc('\n', fp);
break;
case RECTYPE_HLST:
fprintf(fp, "hlst, next=%lu,", rec->r.hlst.next );
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ )
fprintf(fp, " %lu", rec->r.hlst.rnum[i] );
putc('\n', fp);
break;
default:
fprintf(fp, "unknown type %d\n", rec->rectype );
break;
}
}
/****************
* read the record with number recnum
* returns: -1 on error, 0 on success
*/
int
tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
{
byte readbuf[TRUST_RECORD_LEN];
const byte *buf, *p;
int rc = 0;
int n, i;
if( db_fd == -1 )
open_db();
buf = get_record_from_cache( recnum );
if( !buf ) {
if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) );
return G10ERR_READ_FILE;
}
n = read( db_fd, readbuf, TRUST_RECORD_LEN);
if( !n ) {
return -1; /* eof */
}
else if( n != TRUST_RECORD_LEN ) {
log_error(_("trustdb: read failed (n=%d): %s\n"), n,
strerror(errno) );
return G10ERR_READ_FILE;
}
buf = readbuf;
}
rec->recnum = recnum;
rec->dirty = 0;
p = buf;
rec->rectype = *p++;
if( expected && rec->rectype != expected ) {
log_error("%lu: read expected rec type %d, got %d\n",
recnum, expected, rec->rectype );
return G10ERR_TRUSTDB;
}
p++; /* skip reserved byte */
switch( rec->rectype ) {
case 0: /* unused (free) record */
break;
case RECTYPE_VER: /* version record */
if( memcmp(buf+1, "gpg", 3 ) ) {
log_error( _("%s: not a trustdb file\n"), db_name );
rc = G10ERR_TRUSTDB;
}
p += 2; /* skip "pgp" */
rec->r.ver.version = *p++;
rec->r.ver.marginals = *p++;
rec->r.ver.completes = *p++;
rec->r.ver.cert_depth = *p++;
p += 4; /* lock flags */
rec->r.ver.created = buftoulong(p); p += 4;
rec->r.ver.modified = buftoulong(p); p += 4;
rec->r.ver.validated= buftoulong(p); p += 4;
rec->r.ver.keyhashtbl=buftoulong(p); p += 4;
rec->r.ver.firstfree =buftoulong(p); p += 4;
rec->r.ver.sdirhashtbl =buftoulong(p); p += 4;
if( recnum ) {
log_error( _("%s: version record with recnum %lu\n"), db_name,
(ulong)recnum );
rc = G10ERR_TRUSTDB;
}
else if( rec->r.ver.version != 2 ) {
log_error( _("%s: invalid file version %d\n"), db_name,
rec->r.ver.version );
rc = G10ERR_TRUSTDB;
}
break;
case RECTYPE_FREE:
rec->r.free.next = buftoulong(p); p += 4;
break;
case RECTYPE_DIR: /*directory record */
rec->r.dir.lid = buftoulong(p); p += 4;
rec->r.dir.keylist = buftoulong(p); p += 4;
rec->r.dir.uidlist = buftoulong(p); p += 4;
rec->r.dir.cacherec = buftoulong(p); p += 4;
rec->r.dir.ownertrust = *p++;
rec->r.dir.dirflags = *p++;
rec->r.dir.validity = *p++;
switch( rec->r.dir.validity ) {
case 0:
case TRUST_UNDEFINED:
case TRUST_NEVER:
case TRUST_MARGINAL:
case TRUST_FULLY:
case TRUST_ULTIMATE:
break;
default:
log_info("lid %lu: invalid validity value - cleared\n", recnum);
}
if( rec->r.dir.lid != recnum ) {
log_error( "%s: dir LID != recnum (%lu,%lu)\n",
db_name, rec->r.dir.lid, (ulong)recnum );
rc = G10ERR_TRUSTDB;
}
break;
case RECTYPE_KEY: /* public key record */
rec->r.key.lid = buftoulong(p); p += 4;
rec->r.key.next = buftoulong(p); p += 4;
p += 7;
rec->r.key.keyflags = *p++;
rec->r.key.pubkey_algo = *p++;
rec->r.key.fingerprint_len = *p++;
if( rec->r.key.fingerprint_len < 1 || rec->r.key.fingerprint_len > 20 )
rec->r.key.fingerprint_len = 20;
memcpy( rec->r.key.fingerprint, p, 20);
break;
case RECTYPE_UID: /* user id record */
rec->r.uid.lid = buftoulong(p); p += 4;
rec->r.uid.next = buftoulong(p); p += 4;
rec->r.uid.prefrec = buftoulong(p); p += 4;
rec->r.uid.siglist = buftoulong(p); p += 4;
rec->r.uid.uidflags = *p++;
p ++;
memcpy( rec->r.uid.namehash, p, 20);
break;
case RECTYPE_PREF: /* preference record */
rec->r.pref.lid = buftoulong(p); p += 4;
rec->r.pref.next = buftoulong(p); p += 4;
memcpy( rec->r.pref.data, p, 30 );
break;
case RECTYPE_SIG:
rec->r.sig.lid = buftoulong(p); p += 4;
rec->r.sig.next = buftoulong(p); p += 4;
for(i=0; i < SIGS_PER_RECORD; i++ ) {
rec->r.sig.sig[i].lid = buftoulong(p); p += 4;
rec->r.sig.sig[i].flag = *p++;
}
break;
case RECTYPE_SDIR: /* shadow directory record */
rec->r.sdir.lid = buftoulong(p); p += 4;
rec->r.sdir.keyid[0]= buftou32(p); p += 4;
rec->r.sdir.keyid[1]= buftou32(p); p += 4;
rec->r.sdir.pubkey_algo = *p++;
p += 3;
rec->r.sdir.hintlist = buftoulong(p);
if( rec->r.sdir.lid != recnum ) {
log_error( "%s: sdir LID != recnum (%lu,%lu)\n",
db_name, rec->r.sdir.lid, (ulong)recnum );
rc = G10ERR_TRUSTDB;
}
break;
case RECTYPE_CACH: /* cache record */
rec->r.cache.lid = buftoulong(p); p += 4;
memcpy(rec->r.cache.blockhash, p, 20); p += 20;
rec->r.cache.trustlevel = *p++;
break;
case RECTYPE_HTBL:
for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) {
rec->r.htbl.item[i] = buftoulong(p); p += 4;
}
break;
case RECTYPE_HLST:
rec->r.hlst.next = buftoulong(p); p += 4;
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
rec->r.hlst.rnum[i] = buftoulong(p); p += 4;
}
break;
default:
log_error( "%s: invalid record type %d at recnum %lu\n",
db_name, rec->rectype, (ulong)recnum );
rc = G10ERR_TRUSTDB;
break;
}
return rc;
}
/****************
* Write the record at RECNUM
*/
int
tdbio_write_record( TRUSTREC *rec )
{
byte buf[TRUST_RECORD_LEN], *p;
int rc = 0;
int i;
ulong recnum = rec->recnum;
if( db_fd == -1 )
open_db();
memset(buf, 0, TRUST_RECORD_LEN);
p = buf;
*p++ = rec->rectype; p++;
switch( rec->rectype ) {
case 0: /* unused record */
break;
case RECTYPE_VER: /* version record */
if( recnum )
BUG();
memcpy(p-1, "gpg", 3 ); p += 2;
*p++ = rec->r.ver.version;
*p++ = rec->r.ver.marginals;
*p++ = rec->r.ver.completes;
*p++ = rec->r.ver.cert_depth;
p += 4; /* skip lock flags */
ulongtobuf(p, rec->r.ver.created); p += 4;
ulongtobuf(p, rec->r.ver.modified); p += 4;
ulongtobuf(p, rec->r.ver.validated); p += 4;
ulongtobuf(p, rec->r.ver.keyhashtbl); p += 4;
ulongtobuf(p, rec->r.ver.firstfree ); p += 4;
ulongtobuf(p, rec->r.ver.sdirhashtbl ); p += 4;
break;
case RECTYPE_FREE:
ulongtobuf(p, rec->r.free.next); p += 4;
break;
case RECTYPE_DIR: /*directory record */
ulongtobuf(p, rec->r.dir.lid); p += 4;
ulongtobuf(p, rec->r.dir.keylist); p += 4;
ulongtobuf(p, rec->r.dir.uidlist); p += 4;
ulongtobuf(p, rec->r.dir.cacherec); p += 4;
*p++ = rec->r.dir.ownertrust;
*p++ = rec->r.dir.dirflags;
*p++ = rec->r.dir.validity;
assert( rec->r.dir.lid == recnum );
break;
case RECTYPE_KEY:
ulongtobuf(p, rec->r.key.lid); p += 4;
ulongtobuf(p, rec->r.key.next); p += 4;
p += 7;
*p++ = rec->r.key.keyflags;
*p++ = rec->r.key.pubkey_algo;
*p++ = rec->r.key.fingerprint_len;
memcpy( p, rec->r.key.fingerprint, 20); p += 20;
break;
case RECTYPE_UID: /* user id record */
ulongtobuf(p, rec->r.uid.lid); p += 4;
ulongtobuf(p, rec->r.uid.next); p += 4;
ulongtobuf(p, rec->r.uid.prefrec); p += 4;
ulongtobuf(p, rec->r.uid.siglist); p += 4;
*p++ = rec->r.uid.uidflags;
p++;
memcpy( p, rec->r.uid.namehash, 20 ); p += 20;
break;
case RECTYPE_PREF:
ulongtobuf(p, rec->r.pref.lid); p += 4;
ulongtobuf(p, rec->r.pref.next); p += 4;
memcpy( p, rec->r.pref.data, 30 );
break;
case RECTYPE_SIG:
ulongtobuf(p, rec->r.sig.lid); p += 4;
ulongtobuf(p, rec->r.sig.next); p += 4;
for(i=0; i < SIGS_PER_RECORD; i++ ) {
ulongtobuf(p, rec->r.sig.sig[i].lid); p += 4;
*p++ = rec->r.sig.sig[i].flag;
}
break;
case RECTYPE_SDIR:
ulongtobuf( p, rec->r.sdir.lid); p += 4;
u32tobuf( p, rec->r.sdir.keyid[0] ); p += 4;
u32tobuf( p, rec->r.sdir.keyid[1] ); p += 4;
*p++ = rec->r.sdir.pubkey_algo;
p += 3;
ulongtobuf( p, rec->r.sdir.hintlist );
break;
case RECTYPE_CACH:
ulongtobuf(p, rec->r.cache.lid); p += 4;
memcpy(p, rec->r.cache.blockhash, 20); p += 20;
*p++ = rec->r.cache.trustlevel;
break;
case RECTYPE_HTBL:
for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) {
ulongtobuf( p, rec->r.htbl.item[i]); p += 4;
}
break;
case RECTYPE_HLST:
ulongtobuf( p, rec->r.hlst.next); p += 4;
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
ulongtobuf( p, rec->r.hlst.rnum[i]); p += 4;
}
break;
default:
BUG();
}
rc = put_record_into_cache( recnum, buf );
if( rc )
;
if( rec->rectype == RECTYPE_KEY )
rc = update_keyhashtbl( rec );
else if( rec->rectype == RECTYPE_SDIR )
rc = update_sdirhashtbl( rec );
return rc;
}
int
tdbio_delete_record( ulong recnum )
{
TRUSTREC vr, rec;
int rc;
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, g10_errstr(rc) );
rec.recnum = recnum;
rec.rectype = RECTYPE_FREE;
rec.r.free.next = vr.r.ver.firstfree;
vr.r.ver.firstfree = recnum;
rc = tdbio_write_record( &rec );
if( !rc )
rc = tdbio_write_record( &vr );
return rc;
}
/****************
* create a new record and return its record number
*/
ulong
tdbio_new_recnum()
{
off_t offset;
ulong recnum;
TRUSTREC vr, rec;
int rc;
/* look for unused records */
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
if( rc )
log_fatal( _("%s: error reading version record: %s\n"),
db_name, g10_errstr(rc) );
if( vr.r.ver.firstfree ) {
recnum = vr.r.ver.firstfree;
rc = tdbio_read_record( recnum, &rec, RECTYPE_FREE );
if( rc ) {
log_error( _("%s: error reading free record: %s\n"),
db_name, g10_errstr(rc) );
return rc;
}
/* update dir record */
vr.r.ver.firstfree = rec.r.free.next;
rc = tdbio_write_record( &vr );
if( rc ) {
log_error( _("%s: error writing dir record: %s\n"),
db_name, g10_errstr(rc) );
return rc;
}
/*zero out the new record */
memset( &rec, 0, sizeof rec );
rec.rectype = 0; /* unused record */
rec.recnum = recnum;
rc = tdbio_write_record( &rec );
if( rc )
log_fatal(_("%s: failed to zero a record: %s\n"),
db_name, g10_errstr(rc));
}
else { /* not found, append a new record */
offset = lseek( db_fd, 0, SEEK_END );
if( offset == -1 )
log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) );
recnum = offset / TRUST_RECORD_LEN;
assert(recnum); /* this is will never be the first record */
/* we must write a record, so that the next call to this function
* returns another recnum */
memset( &rec, 0, sizeof rec );
rec.rectype = 0; /* unused record */
rec.recnum = recnum;
rc = 0;
if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
log_error(_("trustdb rec %lu: lseek failed: %s\n"),
recnum, strerror(errno) );
rc = G10ERR_WRITE_FILE;
}
else {
int n = write( db_fd, &rec, TRUST_RECORD_LEN);
if( n != TRUST_RECORD_LEN ) {
log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"),
recnum, n, strerror(errno) );
rc = G10ERR_WRITE_FILE;
}
}
if( rc )
log_fatal(_("%s: failed to append a record: %s\n"),
db_name, g10_errstr(rc));
}
return recnum ;
}
/****************
* Search the trustdb for a key which matches PK and return the dir record
* The local_id of PK is set to the correct value
*/
int
tdbio_search_dir_bypk( PKT_public_key *pk, TRUSTREC *rec )
{
byte fingerprint[MAX_FINGERPRINT_LEN];
size_t fingerlen;
u32 keyid[2];
int rc;
keyid_from_pk( pk, keyid );
fingerprint_from_pk( pk, fingerprint, &fingerlen );
rc = tdbio_search_dir_byfpr( fingerprint, fingerlen,
pk->pubkey_algo, rec );
if( !rc ) {
if( pk->local_id && pk->local_id != rec->recnum )
log_error("%s: found record, but LID from memory does "
"not match recnum (%lu,%lu)\n",
db_name, pk->local_id, rec->recnum );
pk->local_id = rec->recnum;
}
return rc;
}
static int
cmp_krec_fpr( void *dataptr, const TRUSTREC *rec )
{
const struct cmp_krec_fpr_struct *d = dataptr;
return rec->rectype == RECTYPE_KEY
&& ( !d->pubkey_algo || rec->r.key.pubkey_algo == d->pubkey_algo )
&& rec->r.key.fingerprint_len == d->fprlen
&& !memcmp( rec->r.key.fingerprint, d->fpr, d->fprlen );
}
int
tdbio_search_dir_byfpr( const byte *fingerprint, size_t fingerlen,
int pubkey_algo, TRUSTREC *rec )
{
struct cmp_krec_fpr_struct cmpdata;
ulong recnum;
int rc;
assert( fingerlen == 20 || fingerlen == 16 );
/* locate the key using the hash table */
cmpdata.pubkey_algo = pubkey_algo;
cmpdata.fpr = fingerprint;
cmpdata.fprlen = fingerlen;
rc = lookup_hashtable( get_keyhashrec(), fingerprint, fingerlen,
cmp_krec_fpr, &cmpdata, rec );
if( !rc ) {
recnum = rec->r.key.lid;
/* Now read the dir record */
rc = tdbio_read_record( recnum, rec, RECTYPE_DIR);
if( rc )
log_error("%s: can't read dirrec %lu: %s\n",
db_name, recnum, g10_errstr(rc) );
}
return rc;
}
static int
cmp_sdir( void *dataptr, const TRUSTREC *rec )
{
const struct cmp_sdir_struct *d = dataptr;
return rec->rectype == RECTYPE_SDIR
&& ( !d->pubkey_algo || rec->r.sdir.pubkey_algo == d->pubkey_algo )
&& rec->r.sdir.keyid[0] == d->keyid[0]
&& rec->r.sdir.keyid[1] == d->keyid[1];
}
int
tdbio_search_sdir( u32 *keyid, int pubkey_algo, TRUSTREC *rec )
{
struct cmp_sdir_struct cmpdata;
int rc;
byte key[8];
/* locate the shadow dir record using the hash table */
u32tobuf( key , keyid[0] );
u32tobuf( key+4 , keyid[1] );
cmpdata.pubkey_algo = pubkey_algo;
cmpdata.keyid[0] = keyid[0];
cmpdata.keyid[1] = keyid[1];
rc = lookup_hashtable( get_sdirhashrec(), key, 8,
cmp_sdir, &cmpdata, rec );
return rc;
}
diff --git a/g10/tdbio.h b/g10/tdbio.h
index d2d369bed..925c7f93c 100644
--- a/g10/tdbio.h
+++ b/g10/tdbio.h
@@ -1,190 +1,190 @@
/* tdbio.h - Trust database I/O functions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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_TDBIO_H
#define G10_TDBIO_H
#include "host2net.h"
#define TRUST_RECORD_LEN 40
#define SIGS_PER_RECORD ((TRUST_RECORD_LEN-10)/5)
#define ITEMS_PER_HTBL_RECORD ((TRUST_RECORD_LEN-2)/4)
#define ITEMS_PER_HLST_RECORD ((TRUST_RECORD_LEN-6)/5)
#define ITEMS_PER_PREF_RECORD (TRUST_RECORD_LEN-10)
#if ITEMS_PER_PREF_RECORD % 2
#error ITEMS_PER_PREF_RECORD must be even
#endif
#define MAX_LIST_SIGS_DEPTH 20
#define RECTYPE_VER 1
#define RECTYPE_DIR 2
#define RECTYPE_KEY 3
#define RECTYPE_UID 4
#define RECTYPE_PREF 5
#define RECTYPE_SIG 6
#define RECTYPE_SDIR 8
#define RECTYPE_CACH 9
#define RECTYPE_HTBL 10
#define RECTYPE_HLST 11
#define RECTYPE_FREE 254
#define DIRF_CHECKED 1 /* has been checked - bits 1,2,3 are valid */
#define DIRF_VALID 2 /* This key is valid: There is at least */
/* one uid with a selfsignature or an revocation */
#define DIRF_EXPIRED 4 /* the complete key has expired */
#define DIRF_REVOKED 8 /* the complete key has been revoked */
#define DIRF_VALVALID 16 /* The validity field is valid */
#define KEYF_CHECKED 1 /* This key has been checked */
#define KEYF_VALID 2 /* This is a valid (sub)key */
#define KEYF_EXPIRED 4 /* this key is expired */
#define KEYF_REVOKED 8 /* this key has been revoked */
#define UIDF_CHECKED 1 /* user id has been checked - other bits are valid */
#define UIDF_VALID 2 /* this is a valid user id */
#define UIDF_REVOKED 8 /* this user id has been revoked */
#define SIGF_CHECKED 1 /* signature has been checked - bits 0..6 are valid */
#define SIGF_VALID 2 /* the signature is valid */
#define SIGF_EXPIRED 4 /* the key of this signature has expired */
#define SIGF_REVOKED 8 /* this signature has been revoked */
#define SIGF_NOPUBKEY 128 /* there is no pubkey for this sig */
struct trust_record {
int rectype;
int mark;
int dirty; /* for now only used internal by functions */
struct trust_record *next; /* help pointer to build lists in memory */
ulong recnum;
union {
struct { /* version record: */
byte version; /* should be 2 */
byte marginals;
byte completes;
byte cert_depth;
ulong created; /* timestamp of trustdb creation */
ulong modified; /* timestamp of last modification */
ulong validated; /* timestamp of last validation */
ulong keyhashtbl;
ulong firstfree;
ulong sdirhashtbl;
} ver;
struct { /* free record */
ulong next;
} free;
struct { /* directory record */
ulong lid;
ulong keylist; /* List of keys (the first is the primary key)*/
ulong uidlist; /* list of uid records */
ulong cacherec; /* the cache record */
byte ownertrust;
byte dirflags;
byte validity; /* calculated trustlevel */
} dir;
struct { /* primary public key record */
ulong lid;
ulong next; /* next key */
byte keyflags;
byte pubkey_algo;
byte fingerprint_len;
byte fingerprint[20];
} key;
struct { /* user id reord */
ulong lid; /* point back to the directory record */
ulong next; /* points to next user id record */
ulong prefrec; /* recno of preference record */
ulong siglist; /* list of valid signatures (w/o self-sig)*/
byte uidflags;
byte namehash[20]; /* ripemd hash of the username */
} uid;
struct { /* preference record */
ulong lid; /* point back to the directory record */
/* or 0 for a glocal pref record */
ulong next; /* points to next pref record */
byte data[ITEMS_PER_PREF_RECORD];
} pref;
struct { /* signature record */
ulong lid;
ulong next; /* recnno of next record or NULL for last one */
struct {
ulong lid; /* of pubkey record of signator (0=unused) */
byte flag; /* SIGF_xxxxx */
} sig[SIGS_PER_RECORD];
} sig;
struct {
ulong lid;
u32 keyid[2];
byte pubkey_algo;
u32 hintlist;
} sdir;
struct { /* cache record */
ulong lid;
byte blockhash[20];
byte trustlevel; /* calculated trustlevel */
} cache;
struct {
ulong item[ITEMS_PER_HTBL_RECORD];
} htbl;
struct {
ulong next;
ulong rnum[ITEMS_PER_HLST_RECORD]; /* of another record */
} hlst;
} r;
};
typedef struct trust_record TRUSTREC;
typedef struct {
ulong lid; /* localid */
ulong sigrec;
ulong sig_lid; /* returned signatures LID */
unsigned sig_flag; /* returned signature record flag */
struct { /* internal data */
int init_done;
int eof;
TRUSTREC rec;
ulong nextuid;
int index;
} ctl;
} SIGREC_CONTEXT;
/*-- tdbio.c --*/
int tdbio_set_dbname( const char *new_dbname, int create );
const char *tdbio_get_dbname(void);
void tdbio_dump_record( TRUSTREC *rec, FILE *fp );
int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected );
int tdbio_write_record( TRUSTREC *rec );
int tdbio_db_matches_options(void);
int tdbio_is_dirty(void);
int tdbio_sync(void);
int tdbio_begin_transaction(void);
int tdbio_end_transaction(void);
int tdbio_cancel_transaction(void);
int tdbio_delete_record( ulong recnum );
ulong tdbio_new_recnum(void);
int tdbio_search_dir_bypk( PKT_public_key *pk, TRUSTREC *rec );
int tdbio_search_dir_byfpr( const byte *fingerprint, size_t fingerlen,
int pubkey_algo, TRUSTREC *rec );
int tdbio_search_sdir( u32 *keyid, int pubkey_algo, TRUSTREC *rec );
#endif /*G10_TDBIO_H*/
diff --git a/g10/textfilter.c b/g10/textfilter.c
index fc81a9136..9e820d159 100644
--- a/g10/textfilter.c
+++ b/g10/textfilter.c
@@ -1,143 +1,143 @@
/* textfilter.c
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "errors.h"
#include "iobuf.h"
#include "memory.h"
#include "util.h"
#include "filter.h"
static int
read_line( byte *buf, size_t *r_buflen, IOBUF a )
{
int c;
int rc = 0;
byte *p;
size_t buflen;
int no_lf=0;
size_t n;
buflen = *r_buflen;
assert(buflen >= 20 );
buflen -= 3; /* leave some room for CR,LF and one extra */
for(c=0, n=0; n < buflen && (c=iobuf_get(a)) != -1 && c != '\n'; )
buf[n++] = c;
buf[n] = 0;
if( c == -1 ) {
rc = -1;
if( !n || buf[n-1] != '\n' )
no_lf = 1;
}
else if( c != '\n' ) {
IOBUF b = iobuf_temp();
while( (c=iobuf_get(a)) != -1 && c != '\n' ) {
iobuf_put(b,c);
if( c != ' ' && c != '\t' && c != '\r' )
break;
}
if( c == '\n' ) { /* okay we can skip the rest of the line */
iobuf_close(b);
}
else {
iobuf_unget_and_close_temp(a,b);
no_lf = 1;
}
}
if( !no_lf ) {
/* append CR,LF after removing trailing wspaces */
for(p=buf+n-1; n; n--, p-- ) {
assert( *p != '\n' );
if( *p != ' ' && *p != '\t' && *p != '\r' ) {
p[1] = '\r';
p[2] = '\n';
n += 2;
break;
}
}
if( !n ) {
buf[0] = '\r';
buf[1] = '\n';
n = 2;
}
}
*r_buflen = n;
return rc;
}
/****************
* The filter is used to make canonical text: Lines are terminated by
* CR, LF, trailing white spaces are removed.
*/
int
text_filter( void *opaque, int control,
IOBUF a, byte *buf, size_t *ret_len)
{
size_t size = *ret_len;
text_filter_context_t *tfx = opaque;
int rc=0;
size_t len, n, nn;
if( control == IOBUFCTRL_UNDERFLOW ) {
assert( size > 30 );
len = 0;
while( !rc && len < size ) {
if( tfx->idx < tfx->len ) { /* flush the last buffer */
n = tfx->len;
for(nn=tfx->idx; len < size && nn < n ; nn++ )
buf[len++] = tfx->buf[nn];
tfx->idx = nn;
continue;
}
if( tfx->eof ) {
rc = -1;
continue;
}
n = DIM(tfx->buf);
tfx->idx = 0;
if( read_line( tfx->buf, &n, a ) == -1 )
tfx->eof = 1;
tfx->len = n;
}
*ret_len = len;
}
else if( control == IOBUFCTRL_DESC )
*(char**)buf = "text_filter";
return rc;
}
diff --git a/g10/trustdb.c b/g10/trustdb.c
index ff05a32ac..de76a25e6 100644
--- a/g10/trustdb.c
+++ b/g10/trustdb.c
@@ -1,3108 +1,3130 @@
/* trustdb.c
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <ctype.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "errors.h"
#include "iobuf.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "trustdb.h"
#include "options.h"
#include "packet.h"
#include "main.h"
#include "i18n.h"
#include "tdbio.h"
#if MAX_FINGERPRINT_LEN > 20
#error Must change structure of trustdb
#endif
struct keyid_list {
struct keyid_list *next;
u32 keyid[2];
};
struct local_id_item {
struct local_id_item *next;
ulong lid;
unsigned flag;
};
struct local_id_table {
struct local_id_table *next; /* only used to keep a list of unused tables */
struct local_id_item *items[16];
};
typedef struct local_id_table *LOCAL_ID_TABLE;
typedef struct trust_info TRUST_INFO;
struct trust_info {
ulong lid;
byte otrust; /* ownertrust (assigned trust) */
byte trust; /* calculated trust (validity) */
};
typedef struct trust_seg_list *TRUST_SEG_LIST;
struct trust_seg_list {
TRUST_SEG_LIST next;
int pathlen;
TRUST_INFO path[1];
};
struct enum_cert_paths_ctx {
int init;
TRUST_SEG_LIST tsl_head;
TRUST_SEG_LIST tsl;
int idx;
};
struct recno_list_struct {
struct recno_list_struct *next;
ulong recno;
int type;
};
typedef struct recno_list_struct *RECNO_LIST;
static int walk_sigrecs( SIGREC_CONTEXT *c );
static LOCAL_ID_TABLE new_lid_table(void);
static void release_lid_table( LOCAL_ID_TABLE tbl );
static int ins_lid_table_item( LOCAL_ID_TABLE tbl, ulong lid, unsigned flag );
static int qry_lid_table_flag( LOCAL_ID_TABLE tbl, ulong lid, unsigned *flag );
static void print_user_id( const char *text, u32 *keyid );
static void sort_tsl_list( TRUST_SEG_LIST *trust_seg_list );
static int list_sigs( ulong pubkey_id );
static int do_check( TRUSTREC *drec, unsigned *trustlevel );
static int get_dir_record( PKT_public_key *pk, TRUSTREC *rec );
static void upd_pref_record( TRUSTREC *urec, u32 *keyid, PKT_signature *sig );
static void upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
TRUSTREC *drec, RECNO_LIST *recno_list, int recheck,
TRUSTREC *urec, const byte *uidhash, int revoke );
static struct keyid_list *trusted_key_list;
/* a table used to keep track of ultimately trusted keys
* which are the ones from our secrings and the trusted keys */
static LOCAL_ID_TABLE ultikey_table;
/* list of unused lid items and tables */
static LOCAL_ID_TABLE unused_lid_tables;
static struct local_id_item *unused_lid_items;
#define HEXTOBIN(a) ( (a) >= '0' && (a) <= '9' ? ((a)-'0') : \
(a) >= 'A' && (a) <= 'F' ? ((a)-'A'+10) : ((a)-'a'+10))
/**********************************************
*********** record read write **************
**********************************************/
static void
die_invalid_db()
{
log_error(_(
"The trust DB is corrupted; please run \"gpgm --fix-trust-db\".\n") );
g10_exit(2);
}
/****************
* Read a record but die if it does not exist
*/
static void
read_record( ulong recno, TRUSTREC *rec, int rectype )
{
int rc = tdbio_read_record( recno, rec, rectype );
if( !rc )
return;
log_error(_("trust record %lu, req type %d: read failed: %s\n"),
recno, rectype, g10_errstr(rc) );
die_invalid_db();
}
/****************
* Wirte a record but die on error
*/
static void
write_record( TRUSTREC *rec )
{
int rc = tdbio_write_record( rec );
if( !rc )
return;
log_error(_("trust record %lu, type %d: write failed: %s\n"),
rec->recnum, rec->rectype, g10_errstr(rc) );
die_invalid_db();
}
/****************
* Delete a record but die on error
*/
static void
delete_record( ulong recno )
{
int rc = tdbio_delete_record( recno );
if( !rc )
return;
log_error(_("trust record %lu: delete failed: %s\n"),
recno, g10_errstr(rc) );
die_invalid_db();
}
/****************
* sync the db
*/
static void
do_sync( )
{
int rc = tdbio_sync();
if( !rc )
return;
log_error(_("trust db: sync failed: %s\n"), g10_errstr(rc) );
g10_exit(2);
}
/**********************************************
************* list helpers *******************
**********************************************/
/****************
* Insert a new item into a recno list
*/
static void
ins_recno_list( RECNO_LIST *head, ulong recno, int type )
{
RECNO_LIST item = m_alloc( sizeof *item );
item->recno = recno;
item->type = type;
item->next = *head;
*head = item;
}
static RECNO_LIST
qry_recno_list( RECNO_LIST list, ulong recno, int type )
{
for( ; list; list = list->next ) {
if( list->recno == recno && (!type || list->type == type) )
return list;
}
return NULL;
}
static void
rel_recno_list( RECNO_LIST *head )
{
RECNO_LIST r, r2;
for(r = *head; r; r = r2 ) {
r2 = r->next;
m_free(r);
}
*head = NULL;
}
static LOCAL_ID_TABLE
new_lid_table(void)
{
LOCAL_ID_TABLE a;
a = unused_lid_tables;
if( a ) {
unused_lid_tables = a->next;
memset( a, 0, sizeof *a );
}
else
a = m_alloc_clear( sizeof *a );
return a;
}
static void
release_lid_table( LOCAL_ID_TABLE tbl )
{
struct local_id_item *a, *a2;
int i;
for(i=0; i < 16; i++ ) {
for(a=tbl->items[i]; a; a = a2 ) {
a2 = a->next;
a->next = unused_lid_items;
unused_lid_items = a;
}
}
tbl->next = unused_lid_tables;
unused_lid_tables = tbl;
}
/****************
* Add a new item to the table or return 1 if we already have this item
*/
static int
ins_lid_table_item( LOCAL_ID_TABLE tbl, ulong lid, unsigned flag )
{
struct local_id_item *a;
for( a = tbl->items[lid & 0x0f]; a; a = a->next )
if( a->lid == lid )
return 1;
a = unused_lid_items;
if( a )
unused_lid_items = a->next;
else
a = m_alloc( sizeof *a );
a->lid = lid;
a->flag = flag;
a->next = tbl->items[lid & 0x0f];
tbl->items[lid & 0x0f] = a;
return 0;
}
static int
qry_lid_table_flag( LOCAL_ID_TABLE tbl, ulong lid, unsigned *flag )
{
struct local_id_item *a;
for( a = tbl->items[lid & 0x0f]; a; a = a->next )
if( a->lid == lid ) {
if( flag )
*flag = a->flag;
return 0;
}
return -1;
}
/****************
* Return the keyid from the primary key identified by LID.
*/
int
keyid_from_lid( ulong lid, u32 *keyid )
{
TRUSTREC rec;
int rc;
rc = tdbio_read_record( lid, &rec, 0 );
if( rc ) {
log_error(_("error reading dir record for LID %lu: %s\n"),
lid, g10_errstr(rc));
return G10ERR_TRUSTDB;
}
if( rec.rectype == RECTYPE_SDIR )
return 0;
if( rec.rectype != RECTYPE_DIR ) {
log_error(_("lid %lu: expected dir record, got type %d\n"),
lid, rec.rectype );
return G10ERR_TRUSTDB;
}
if( !rec.r.dir.keylist ) {
log_error(_("no primary key for LID %lu\n"), lid );
return G10ERR_TRUSTDB;
}
rc = tdbio_read_record( rec.r.dir.keylist, &rec, RECTYPE_KEY );
if( rc ) {
log_error(_("error reading primary key for LID %lu: %s\n"),
lid, g10_errstr(rc));
return G10ERR_TRUSTDB;
}
keyid_from_fingerprint( rec.r.key.fingerprint, rec.r.key.fingerprint_len,
keyid );
return 0;
}
ulong
lid_from_keyblock( KBNODE keyblock )
{
KBNODE node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
PKT_public_key *pk;
if( !node )
BUG();
pk = node->pkt->pkt.public_key;
if( !pk->local_id ) {
TRUSTREC rec;
get_dir_record( pk, &rec );
}
return pk->local_id;
}
/****************
* Walk through the signatures of a public key.
* The caller must provide a context structure, with all fields set
* to zero, but the local_id field set to the requested key;
* This function does not change this field. On return the context
* is filled with the local-id of the signature and the signature flag.
* No fields should be changed (clearing all fields and setting
* pubkeyid is okay to continue with an other pubkey)
* Returns: 0 - okay, -1 for eof (no more sigs) or any other errorcode
*/
static int
walk_sigrecs( SIGREC_CONTEXT *c )
{
TRUSTREC *r;
ulong rnum;
if( c->ctl.eof )
return -1;
r = &c->ctl.rec;
if( !c->ctl.init_done ) {
c->ctl.init_done = 1;
read_record( c->lid, r, 0 );
if( r->rectype != RECTYPE_DIR ) {
c->ctl.eof = 1;
return -1; /* return eof */
}
c->ctl.nextuid = r->r.dir.uidlist;
/* force a read */
c->ctl.index = SIGS_PER_RECORD;
r->r.sig.next = 0;
}
/* need a loop to skip over deleted sigs */
do {
if( c->ctl.index >= SIGS_PER_RECORD ) { /* read the record */
rnum = r->r.sig.next;
if( !rnum && c->ctl.nextuid ) { /* read next uid record */
read_record( c->ctl.nextuid, r, RECTYPE_UID );
c->ctl.nextuid = r->r.uid.next;
rnum = r->r.uid.siglist;
}
if( !rnum ) {
c->ctl.eof = 1;
return -1; /* return eof */
}
read_record( rnum, r, RECTYPE_SIG );
if( r->r.sig.lid != c->lid ) {
log_error(_("chained sigrec %lu has a wrong owner\n"), rnum );
c->ctl.eof = 1;
die_invalid_db();
}
c->ctl.index = 0;
}
} while( !r->r.sig.sig[c->ctl.index++].lid );
c->sig_lid = r->r.sig.sig[c->ctl.index-1].lid;
c->sig_flag = r->r.sig.sig[c->ctl.index-1].flag;
return 0;
}
/***********************************************
************* Trust stuff ******************
***********************************************/
static int
trust_letter( unsigned value )
{
switch( value ) {
case TRUST_UNKNOWN: return '-';
case TRUST_EXPIRED: return 'e';
case TRUST_UNDEFINED: return 'q';
case TRUST_NEVER: return 'n';
case TRUST_MARGINAL: return 'm';
case TRUST_FULLY: return 'f';
case TRUST_ULTIMATE: return 'u';
default: return 0 ;
}
}
void
register_trusted_key( const char *string )
{
u32 keyid[2];
struct keyid_list *r;
if( classify_user_id( string, keyid, NULL, NULL, NULL ) != 11 ) {
log_error(_("'%s' is not a valid long keyID\n"), string );
return;
}
for( r = trusted_key_list; r; r = r->next )
if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] )
return;
r = m_alloc( sizeof *r );
r->keyid[0] = keyid[0];
r->keyid[1] = keyid[1];
r->next = trusted_key_list;
trusted_key_list = r;
}
/****************
* Verify that all our public keys are in the trustdb.
*/
static int
verify_own_keys()
{
int rc;
void *enum_context = NULL;
PKT_secret_key *sk = m_alloc_clear( sizeof *sk );
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
u32 keyid[2];
struct keyid_list *kl;
/* put the trusted keys into the trusted key table */
for( kl = trusted_key_list; kl; kl = kl->next ) {
keyid[0] = kl->keyid[0];
keyid[1] = kl->keyid[1];
/* get the public key */
memset( pk, 0, sizeof *pk );
rc = get_pubkey( pk, keyid );
if( rc ) {
log_info(_("key %08lX: no public key for trusted key - skipped\n"),
(ulong)keyid[1] );
}
else {
/* make sure that the pubkey is in the trustdb */
rc = query_trust_record( pk );
if( rc == -1 ) { /* put it into the trustdb */
rc = insert_trust_record( pk );
if( rc ) {
log_error(_("key %08lX: can't put it into the trustdb\n"),
(ulong)keyid[1] );
}
}
else if( rc ) {
log_error(_("key %08lX: query record failed\n"),
(ulong)keyid[1] );
}
else {
if( ins_lid_table_item( ultikey_table, pk->local_id, 0 ) )
log_error(_("key %08lX: already in trusted key table\n"),
(ulong)keyid[1]);
else if( opt.verbose > 1 )
log_info(_("key %08lX: accepted as trusted key.\n"),
(ulong)keyid[1]);
}
}
release_public_key_parts( pk );
}
while( !(rc=enum_secret_keys( &enum_context, sk, 0 ) ) ) {
int have_pk = 0;
keyid_from_sk( sk, keyid );
if( DBG_TRUST )
log_debug("key %08lX: checking secret key\n", (ulong)keyid[1] );
if( is_secret_key_protected( sk ) < 1 )
log_info(_("NOTE: secret key %08lX is NOT protected.\n"),
(ulong)keyid[1] );
for( kl = trusted_key_list; kl; kl = kl->next ) {
if( kl->keyid[0] == keyid[0] && kl->keyid[1] == keyid[1] )
goto skip; /* already in trusted key table */
}
/* see whether we can access the public key of this secret key */
memset( pk, 0, sizeof *pk );
rc = get_pubkey( pk, keyid );
if( rc ) {
log_info(_("key %08lX: secret key without public key - skipped\n"),
(ulong)keyid[1] );
goto skip;
}
have_pk=1;
if( cmp_public_secret_key( pk, sk ) ) {
log_info(_("key %08lX: secret and public key don't match\n"),
(ulong)keyid[1] );
goto skip;
}
/* make sure that the pubkey is in the trustdb */
rc = query_trust_record( pk );
if( rc == -1 ) { /* put it into the trustdb */
rc = insert_trust_record( pk );
if( rc ) {
log_error(_("key %08lX: can't put it into the trustdb\n"),
(ulong)keyid[1] );
goto skip;
}
}
else if( rc ) {
log_error(_("key %08lX: query record failed\n"), (ulong)keyid[1] );
goto skip;
}
if( DBG_TRUST )
log_debug("key %08lX.%lu: stored into ultikey_table\n",
(ulong)keyid[1], pk->local_id );
if( ins_lid_table_item( ultikey_table, pk->local_id, 0 ) )
log_error(_("key %08lX: already in trusted key table\n"),
(ulong)keyid[1]);
else if( opt.verbose > 1 )
log_info(_("key %08lX: accepted as trusted key.\n"),
(ulong)keyid[1]);
skip:
release_secret_key_parts( sk );
if( have_pk )
release_public_key_parts( pk );
}
if( rc != -1 )
log_error(_("enumerate secret keys failed: %s\n"), g10_errstr(rc) );
else
rc = 0;
/* release the trusted keyid table */
{ struct keyid_list *kl2;
for( kl = trusted_key_list; kl; kl = kl2 ) {
kl2 = kl->next;
m_free( kl );
}
trusted_key_list = NULL;
}
enum_secret_keys( &enum_context, NULL, 0 ); /* free context */
free_secret_key( sk );
free_public_key( pk );
return rc;
}
static void
print_user_id( const char *text, u32 *keyid )
{
char *p;
size_t n;
p = get_user_id( keyid, &n );
if( *text ) {
fputs( text, stdout);
putchar(' ');
}
putchar('\"');
print_string( stdout, p, n, 0 );
putchar('\"');
putchar('\n');
m_free(p);
}
#if 0
static int
print_keyid( FILE *fp, ulong lid )
{
u32 ki[2];
if( keyid_from_lid( lid, ki ) )
return fprintf(fp, "????????.%lu", lid );
else
return fprintf(fp, "%08lX.%lu", (ulong)ki[1], lid );
}
static int
print_trust( FILE *fp, unsigned trust )
{
int c;
switch( trust ) {
case TRUST_UNKNOWN: c = 'o'; break;
case TRUST_EXPIRED: c = 'e'; break;
case TRUST_UNDEFINED: c = 'q'; break;
case TRUST_NEVER: c = 'n'; break;
case TRUST_MARGINAL: c = 'm'; break;
case TRUST_FULLY: c = 'f'; break;
case TRUST_ULTIMATE: c = 'u'; break;
default: fprintf(fp, "%02x", trust ); return 2;
}
putc(c, fp);
return 1;
}
#endif
static int
print_sigflags( FILE *fp, unsigned flags )
{
if( flags & SIGF_CHECKED ) {
fprintf(fp,"%c%c%c",
(flags & SIGF_VALID) ? 'V':'-',
(flags & SIGF_EXPIRED) ? 'E':'-',
(flags & SIGF_REVOKED) ? 'R':'-');
}
else if( flags & SIGF_NOPUBKEY)
fputs("?--", fp);
else
fputs("---", fp);
return 3;
}
/* (a non-recursive algorithm would be easier) */
static int
do_list_sigs( ulong root, ulong pk_lid, int depth,
LOCAL_ID_TABLE lids, unsigned *lineno )
{
SIGREC_CONTEXT sx;
int rc;
u32 keyid[2];
memset( &sx, 0, sizeof sx );
sx.lid = pk_lid;
for(;;) {
rc = walk_sigrecs( &sx ); /* should we replace it and use */
if( rc ) /* use a loop like in collect_paths ??*/
break;
rc = keyid_from_lid( sx.sig_lid, keyid );
if( rc ) {
printf("%6u: %*s????????.%lu:", *lineno, depth*4, "", sx.sig_lid );
print_sigflags( stdout, sx.sig_flag );
putchar('\n');
++*lineno;
}
else {
printf("%6u: %*s%08lX.%lu:", *lineno, depth*4, "",
(ulong)keyid[1], sx.sig_lid );
print_sigflags( stdout, sx.sig_flag );
putchar(' ');
/* check whether we already checked this pk_lid */
if( !qry_lid_table_flag( ultikey_table, sx.sig_lid, NULL ) ) {
print_user_id("[ultimately trusted]", keyid);
++*lineno;
}
else if( sx.sig_lid == pk_lid ) {
printf("[self-signature]\n");
++*lineno;
}
else if( sx.sig_lid == root ) {
printf("[closed]\n");
++*lineno;
}
else if( ins_lid_table_item( lids, sx.sig_lid, *lineno ) ) {
unsigned refline;
qry_lid_table_flag( lids, sx.sig_lid, &refline );
printf("[see line %u]\n", refline);
++*lineno;
}
else if( depth+1 >= MAX_LIST_SIGS_DEPTH ) {
print_user_id( "[too deeply nested]", keyid );
++*lineno;
}
else {
print_user_id( "", keyid );
++*lineno;
rc = do_list_sigs( root, sx.sig_lid, depth+1, lids, lineno );
if( rc )
break;
}
}
}
return rc==-1? 0 : rc;
}
/****************
* List all signatures of a public key
*/
static int
list_sigs( ulong pubkey_id )
{
int rc;
u32 keyid[2];
LOCAL_ID_TABLE lids;
unsigned lineno = 1;
rc = keyid_from_lid( pubkey_id, keyid );
if( rc )
return rc;
printf("Signatures of %08lX.%lu ", (ulong)keyid[1], pubkey_id );
print_user_id("", keyid);
printf("----------------------\n");
lids = new_lid_table();
rc = do_list_sigs( pubkey_id, pubkey_id, 0, lids, &lineno );
putchar('\n');
release_lid_table(lids);
return rc;
}
/****************
* List all records of a public key
*/
static int
list_records( ulong lid )
{
int rc;
TRUSTREC dr, ur, rec;
ulong recno;
rc = tdbio_read_record( lid, &dr, RECTYPE_DIR );
if( rc ) {
log_error(_("lid %lu: read dir record failed: %s\n"),
lid, g10_errstr(rc));
return rc;
}
tdbio_dump_record( &dr, stdout );
for( recno=dr.r.dir.keylist; recno; recno = rec.r.key.next ) {
rc = tdbio_read_record( recno, &rec, 0 );
if( rc ) {
log_error(_("lid %lu: read key record failed: %s\n"),
lid, g10_errstr(rc));
return rc;
}
tdbio_dump_record( &rec, stdout );
}
for( recno=dr.r.dir.uidlist; recno; recno = ur.r.uid.next ) {
rc = tdbio_read_record( recno, &ur, RECTYPE_UID );
if( rc ) {
log_error(_("lid %lu: read uid record failed: %s\n"),
lid, g10_errstr(rc));
return rc;
}
tdbio_dump_record( &ur, stdout );
/* preference records */
for(recno=ur.r.uid.prefrec; recno; recno = rec.r.pref.next ) {
rc = tdbio_read_record( recno, &rec, RECTYPE_PREF );
if( rc ) {
log_error(_("lid %lu: read pref record failed: %s\n"),
lid, g10_errstr(rc));
return rc;
}
tdbio_dump_record( &rec, stdout );
}
/* sig records */
for(recno=ur.r.uid.siglist; recno; recno = rec.r.sig.next ) {
rc = tdbio_read_record( recno, &rec, RECTYPE_SIG );
if( rc ) {
log_error(_("lid %lu: read sig record failed: %s\n"),
lid, g10_errstr(rc));
return rc;
}
tdbio_dump_record( &rec, stdout );
}
}
/* add cache record dump here */
return rc;
}
/****************
* stack is an array of (max_path+1) elements. If trust_seg_head is not
* NULL it is a pointer to a variable which will receive a linked list
* of trust paths - The caller has to free the memory.
*/
static int
collect_paths( int depth, int max_depth, int all, TRUSTREC *drec,
TRUST_INFO *stack, TRUST_SEG_LIST *trust_seg_head )
{
ulong rn, uidrn;
int marginal=0;
int fully=0;
LOCAL_ID_TABLE sigs_seen = NULL;
if( depth >= max_depth ) /* max cert_depth reached */
return TRUST_UNDEFINED;
stack[depth].lid = drec->r.dir.lid;
stack[depth].otrust = drec->r.dir.ownertrust;
stack[depth].trust = 0;
{ int i;
for(i=0; i < depth; i++ )
if( stack[i].lid == drec->r.dir.lid )
return TRUST_UNDEFINED; /* closed (we already visited this lid) */
}
if( !qry_lid_table_flag( ultikey_table, drec->r.dir.lid, NULL ) ) {
/* we are at the end of a path */
TRUST_SEG_LIST tsl;
int i;
stack[depth].trust = TRUST_ULTIMATE;
stack[depth].otrust = TRUST_ULTIMATE;
if( trust_seg_head ) {
/* we can now put copy our current stack to the trust_seg_list */
tsl = m_alloc( sizeof *tsl + (depth+1)*sizeof( TRUST_INFO ) );
for(i=0; i <= depth; i++ )
tsl->path[i] = stack[i];
tsl->pathlen = i;
tsl->next = *trust_seg_head;
*trust_seg_head = tsl;
}
return TRUST_ULTIMATE;
}
/* loop over all user-ids */
if( !all )
sigs_seen = new_lid_table();
for( rn = drec->r.dir.uidlist; rn; rn = uidrn ) {
TRUSTREC rec; /* used for uids and sigs */
ulong sigrn;
read_record( rn, &rec, RECTYPE_UID );
uidrn = rec.r.uid.next;
if( !(rec.r.uid.uidflags & UIDF_CHECKED) )
continue; /* user id has not been checked */
if( !(rec.r.uid.uidflags & UIDF_VALID) )
continue; /* user id is not valid */
if( (rec.r.uid.uidflags & UIDF_REVOKED) )
continue; /* user id has been revoked */
/* loop over all signature records */
for( rn = rec.r.uid.siglist; rn; rn = sigrn ) {
int i;
read_record( rn, &rec, RECTYPE_SIG );
sigrn = rec.r.sig.next;
for(i=0; i < SIGS_PER_RECORD; i++ ) {
TRUSTREC tmp;
int ot, nt;
int unchecked = 0;
if( !rec.r.sig.sig[i].lid )
continue; /* skip deleted sigs */
if( !(rec.r.sig.sig[i].flag & SIGF_CHECKED) ) {
if( !all )
continue; /* skip unchecked signatures */
unchecked = 1;
}
else {
if( !(rec.r.sig.sig[i].flag & SIGF_VALID) )
continue; /* skip invalid signatures */
if( (rec.r.sig.sig[i].flag & SIGF_EXPIRED) )
continue; /* skip expired signatures */
if( (rec.r.sig.sig[i].flag & SIGF_REVOKED) )
continue; /* skip revoked signatures */
}
/* visit every signer only once (a signer may have
* signed more than one user ID) */
if( sigs_seen && ins_lid_table_item( sigs_seen,
rec.r.sig.sig[i].lid, 0) )
continue; /* we already have this one */
read_record( rec.r.sig.sig[i].lid, &tmp, 0 );
if( tmp.rectype != RECTYPE_DIR ) {
if( tmp.rectype != RECTYPE_SDIR )
log_info("oops: lid %lu: sig %lu has rectype %d"
" - skipped\n",
drec->r.dir.lid, tmp.recnum, tmp.rectype );
continue;
}
ot = tmp.r.dir.ownertrust & TRUST_MASK;
if( ot >= TRUST_FULLY )
ot = TRUST_FULLY; /* just in case */
nt = collect_paths( depth+1, max_depth, all, &tmp, stack,
trust_seg_head );
nt &= TRUST_MASK;
if( nt < TRUST_MARGINAL || unchecked ) {
continue;
}
if( nt == TRUST_ULTIMATE ) {
/* we have signed this key and only in this special case
* we assume that this one is fully trusted */
if( !all ) {
if( sigs_seen )
release_lid_table( sigs_seen );
return (stack[depth].trust = TRUST_FULLY);
}
}
if( nt > ot )
nt = ot;
if( nt >= TRUST_FULLY )
fully++;
if( nt >= TRUST_MARGINAL )
marginal++;
if( fully >= opt.completes_needed
|| marginal >= opt.marginals_needed ) {
if( !all ) {
if( sigs_seen )
release_lid_table( sigs_seen );
return (stack[depth].trust = TRUST_FULLY);
}
}
}
}
}
if( sigs_seen )
release_lid_table( sigs_seen );
if( all && ( fully >= opt.completes_needed
|| marginal >= opt.marginals_needed ) ) {
return (stack[depth].trust = TRUST_FULLY );
}
if( marginal ) {
return (stack[depth].trust = TRUST_MARGINAL);
}
return (stack[depth].trust=TRUST_UNDEFINED);
}
/****************
* Given the directory record of a key, check whether we can
* find a path to an ultimately trusted key. We do this by
* checking all key signatures up to a some depth.
*/
static int
verify_key( int max_depth, TRUSTREC *drec )
{
TRUST_INFO *tmppath = m_alloc_clear( (max_depth+1)* sizeof *tmppath );
int tr;
tr = collect_paths( 0, max_depth, 0, drec, tmppath, NULL );
m_free( tmppath );
return tr;
}
/****************
* we have the pubkey record and all needed informations are in the trustdb
* but nothing more is known.
*/
static int
do_check( TRUSTREC *dr, unsigned *validity )
{
if( !dr->r.dir.keylist ) {
log_error(_("Ooops, no keys\n"));
return G10ERR_TRUSTDB;
}
if( !dr->r.dir.uidlist ) {
log_error(_("Ooops, no user ids\n"));
return G10ERR_TRUSTDB;
}
if( tdbio_db_matches_options()
&& (dr->r.dir.dirflags & DIRF_VALVALID)
&& dr->r.dir.validity )
*validity = dr->r.dir.validity;
else {
*validity = verify_key( opt.max_cert_depth, dr );
if( (*validity & TRUST_MASK) >= TRUST_UNDEFINED
&& tdbio_db_matches_options() ) {
/* update the cached validity value */
dr->r.dir.validity = (*validity & TRUST_MASK);
dr->r.dir.dirflags |= DIRF_VALVALID;
write_record( dr );
}
}
if( dr->r.dir.dirflags & DIRF_REVOKED )
*validity |= TRUST_FLAG_REVOKED;
return 0;
}
/****************
* Perform some checks over the trustdb
* level 0: only open the db
* 1: used for initial program startup
*/
int
init_trustdb( int level, const char *dbname )
{
int rc=0;
if( !ultikey_table )
ultikey_table = new_lid_table();
if( !level || level==1 ) {
rc = tdbio_set_dbname( dbname, !!level );
if( rc )
return rc;
if( !level )
return 0;
/* verify that our own keys are in the trustDB
* or move them to the trustdb. */
rc = verify_own_keys();
/* should we check whether there is no other ultimately trusted
* key in the database? */
}
else
BUG();
return rc;
}
void
list_trustdb( const char *username )
{
TRUSTREC rec;
if( username && *username == '#' ) {
int rc;
ulong lid = atoi(username+1);
if( (rc = list_records( lid)) )
log_error(_("user '%s' read problem: %s\n"),
username, g10_errstr(rc));
else if( (rc = list_sigs( lid )) )
log_error(_("user '%s' list problem: %s\n"),
username, g10_errstr(rc));
}
else if( username ) {
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
int rc;
if( (rc = get_pubkey_byname( NULL, pk, username, NULL )) )
log_error(_("user '%s' not found: %s\n"), username, g10_errstr(rc) );
else if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 )
log_error(_("problem finding '%s' in trustdb: %s\n"),
username, g10_errstr(rc));
else if( rc == -1 )
log_error(_("user '%s' not in trustdb\n"), username);
else if( (rc = list_records( pk->local_id)) )
log_error(_("user '%s' read problem: %s\n"),
username, g10_errstr(rc));
else if( (rc = list_sigs( pk->local_id )) )
log_error(_("user '%s' list problem: %s\n"),
username, g10_errstr(rc));
free_public_key( pk );
}
else {
ulong recnum;
int i;
printf("TrustDB: %s\n", tdbio_get_dbname() );
for(i=9+strlen(tdbio_get_dbname()); i > 0; i-- )
putchar('-');
putchar('\n');
for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ )
tdbio_dump_record( &rec, stdout );
}
}
/****************
* Print a list of all defined owner trust value.
*/
void
export_ownertrust()
{
TRUSTREC rec;
TRUSTREC rec2;
ulong recnum;
int i;
byte *p;
int rc;
printf(_("# List of assigned trustvalues, created %s\n"
"# (Use \"gpgm --import-ownertrust\" to restore them)\n"),
asctimestamp( make_timestamp() ) );
for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) {
if( rec.rectype == RECTYPE_DIR ) {
if( !rec.r.dir.keylist ) {
log_error(_("directory record w/o primary key\n"));
continue;
}
if( !rec.r.dir.ownertrust )
continue;
rc = tdbio_read_record( rec.r.dir.keylist, &rec2, RECTYPE_KEY);
if( rc ) {
log_error(_("error reading key record: %s\n"), g10_errstr(rc));
continue;
}
p = rec2.r.key.fingerprint;
for(i=0; i < rec2.r.key.fingerprint_len; i++, p++ )
printf("%02X", *p );
printf(":%u:\n", (unsigned)rec.r.dir.ownertrust );
}
}
}
void
import_ownertrust( const char *fname )
{
FILE *fp;
int is_stdin=0;
char line[256];
char *p;
size_t n, fprlen;
unsigned otrust;
if( !fname || (*fname == '-' && !fname[1]) ) {
fp = stdin;
fname = "[stdin]";
is_stdin = 1;
}
else if( !(fp = fopen( fname, "r" )) ) {
log_error_f(fname, _("can't open file: %s\n"), strerror(errno) );
return;
}
while( fgets( line, DIM(line)-1, fp ) ) {
TRUSTREC rec;
int rc;
if( !*line || *line == '#' )
continue;
n = strlen(line);
if( line[n-1] != '\n' ) {
log_error_f(fname, _("line too long\n") );
/* ... or last line does not have a LF */
break; /* can't continue */
}
for(p = line; *p && *p != ':' ; p++ )
if( !isxdigit(*p) )
break;
if( *p != ':' ) {
log_error_f(fname, _("error: missing colon\n") );
continue;
}
fprlen = p - line;
if( fprlen != 32 && fprlen != 40 ) {
log_error_f(fname, _("error: invalid fingerprint\n") );
continue;
}
if( sscanf(p, ":%u:", &otrust ) != 1 ) {
log_error_f(fname, _("error: no ownertrust value\n") );
continue;
}
if( !otrust )
continue; /* no otrust defined - no need to update or insert */
/* convert the ascii fingerprint to binary */
for(p=line, fprlen=0; *p != ':'; p += 2 )
line[fprlen++] = HEXTOBIN(p[0]) * 16 + HEXTOBIN(p[1]);
line[fprlen] = 0;
repeat:
rc = tdbio_search_dir_byfpr( line, fprlen, 0, &rec );
if( !rc ) { /* found: update */
if( rec.r.dir.ownertrust )
log_info(_("LID %lu: changing trust from %u to %u\n"),
rec.r.dir.lid, rec.r.dir.ownertrust, otrust );
else
log_info(_("LID %lu: setting trust to %u\n"),
rec.r.dir.lid, otrust );
rec.r.dir.ownertrust = otrust;
write_record( &rec );
}
else if( rc == -1 ) { /* not found; get the key from the ring */
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
log_info_f(fname, _("key not in trustdb, searching ring.\n"));
rc = get_pubkey_byfprint( pk, line, fprlen );
if( rc )
log_info_f(fname, _("key not in ring: %s\n"), g10_errstr(rc));
else {
rc = query_trust_record( pk ); /* only as assertion */
if( rc != -1 )
log_error_f(fname, _("Oops: key is now in trustdb???\n"));
else {
rc = insert_trust_record( pk );
if( !rc )
goto repeat; /* update the ownertrust */
log_error_f(fname, _("insert trust record failed: %s\n"),
g10_errstr(rc) );
}
}
}
else /* error */
log_error_f(fname, _("error finding dir record: %s\n"),
g10_errstr(rc));
}
if( ferror(fp) )
log_error_f(fname, _("read error: %s\n"), strerror(errno) );
if( !is_stdin )
fclose(fp);
do_sync();
}
static void
print_path( int pathlen, TRUST_INFO *path, FILE *fp, ulong highlight )
{
int rc, c, i;
u32 keyid[2];
char *p;
size_t n;
for( i = 0; i < pathlen; i++ ) {
if( highlight )
fputs(highlight == path[i].lid? "* ":" ", fp );
rc = keyid_from_lid( path[i].lid, keyid );
if( rc )
fprintf(fp, "????????.%lu:", path[i].lid );
else
fprintf(fp,"%08lX.%lu:", (ulong)keyid[1], path[i].lid );
c = trust_letter(path[i].otrust);
if( c )
putc( c, fp );
else
fprintf( fp, "%02x", path[i].otrust );
putc('/', fp);
c = trust_letter(path[i].trust);
if( c )
putc( c, fp );
else
fprintf( fp, "%02x", path[i].trust );
putc(' ', fp);
p = get_user_id( keyid, &n );
putc(' ', fp);
putc('\"', fp);
print_string( fp, p, n > 40? 40:n, 0 );
putc('\"', fp);
m_free(p);
putc('\n', fp );
}
}
static int
cmp_tsl_array( const void *xa, const void *xb )
{
TRUST_SEG_LIST a = *(TRUST_SEG_LIST*)xa;
TRUST_SEG_LIST b = *(TRUST_SEG_LIST*)xb;
return a->pathlen - b->pathlen;
}
static void
sort_tsl_list( TRUST_SEG_LIST *trust_seg_list )
{
TRUST_SEG_LIST *array, *tail, tsl;
size_t n;
for(n=0, tsl = *trust_seg_list; tsl; tsl = tsl->next )
n++;
array = m_alloc( (n+1) * sizeof *array );
for(n=0, tsl = *trust_seg_list; tsl; tsl = tsl->next )
array[n++] = tsl;
array[n] = NULL;
qsort( array, n, sizeof *array, cmp_tsl_array );
*trust_seg_list = NULL;
tail = trust_seg_list;
for(n=0; (tsl=array[n]); n++ ) {
*tail = tsl;
tail = &tsl->next;
}
m_free( array );
}
void
list_trust_path( const char *username )
{
int rc;
TRUSTREC rec;
TRUST_INFO *tmppath;
TRUST_SEG_LIST trust_seg_list, tsl, tsl2;
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
if( (rc = get_pubkey_byname(NULL, pk, username, NULL )) )
log_error(_("user '%s' not found: %s\n"), username, g10_errstr(rc) );
else if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 )
log_error(_("problem finding '%s' in trustdb: %s\n"),
username, g10_errstr(rc));
else if( rc == -1 ) {
log_info(_("user '%s' not in trustdb - inserting\n"), username);
rc = insert_trust_record( pk );
if( rc )
log_error(_("failed to put '%s' into trustdb: %s\n"),
username, g10_errstr(rc));
else {
assert( pk->local_id );
}
}
free_public_key( pk );
/* collect the paths */
tmppath = m_alloc_clear( (opt.max_cert_depth+1)* sizeof *tmppath );
trust_seg_list = NULL;
collect_paths( 0, opt.max_cert_depth, 1, &rec, tmppath, &trust_seg_list );
m_free( tmppath );
sort_tsl_list( &trust_seg_list );
/* and now print them */
for(tsl = trust_seg_list; tsl; tsl = tsl->next ) {
print_path( tsl->pathlen, tsl->path, stdout, 0 );
if( tsl->next )
putchar('\n');
}
/* release the list */
for(tsl = trust_seg_list; tsl; tsl = tsl2 ) {
tsl2 = tsl->next;
m_free( tsl );
}
trust_seg_list = NULL;
}
/****************
* Check the complete trustdb or only the entries for the given username.
* We check the complete database. If a username is given or the special
* username "*" is used, a complete recheck is done. With no user ID
* only the records which are not yet checkd are now checked.
*/
void
check_trustdb( const char *username )
{
TRUSTREC rec;
KBNODE keyblock = NULL;
KBPOS kbpos;
int rc;
int recheck = username && *username == '*' && !username[1];
if( username && !recheck ) {
rc = find_keyblock_byname( &kbpos, username );
if( !rc )
rc = read_keyblock( &kbpos, &keyblock );
if( rc ) {
log_error(_("%s: keyblock read problem: %s\n"),
username, g10_errstr(rc));
}
else {
int modified;
rc = update_trust_record( keyblock, 1, &modified );
if( rc == -1 ) { /* not yet in trustdb: insert */
rc = insert_trust_record(
find_kbnode( keyblock, PKT_PUBLIC_KEY
) ->pkt->pkt.public_key );
}
if( rc )
log_error(_("%s: update failed: %s\n"),
username, g10_errstr(rc) );
else if( modified )
log_info(_("%s: updated\n"), username );
else
log_info(_("%s: okay\n"), username );
}
release_kbnode( keyblock ); keyblock = NULL;
}
else {
ulong recnum;
ulong count=0, upd_count=0, err_count=0, skip_count=0;
for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) {
if( rec.rectype == RECTYPE_DIR ) {
TRUSTREC tmp;
int modified;
if( !rec.r.dir.keylist ) {
log_info(_("lid %lu: dir record w/o key - skipped\n"),
recnum);
count++;
skip_count++;
continue;
}
read_record( rec.r.dir.keylist, &tmp, RECTYPE_KEY );
rc = get_keyblock_byfprint( &keyblock,
tmp.r.key.fingerprint,
tmp.r.key.fingerprint_len );
if( rc ) {
log_error(_("lid %lu: keyblock not found: %s\n"),
recnum, g10_errstr(rc) );
count++;
skip_count++;
continue;
}
rc = update_trust_record( keyblock, recheck, &modified );
if( rc ) {
log_error(_("lid %lu: update failed: %s\n"),
recnum, g10_errstr(rc) );
err_count++;
}
else if( modified ) {
if( opt.verbose )
log_info(_("lid %lu: updated\n"), recnum );
upd_count++;
}
else if( opt.verbose > 1 )
log_info(_("lid %lu: okay\n"), recnum );
release_kbnode( keyblock ); keyblock = NULL;
if( !(++count % 100) )
log_info(_("%lu keys so far processed\n"), count);
}
}
log_info(_("%lu keys processed\n"), count);
if( skip_count )
log_info(_("\t%lu keys skipped\n"), skip_count);
if( err_count )
log_info(_("\t%lu keys with errors\n"), err_count);
if( upd_count )
log_info(_("\t%lu keys updated\n"), upd_count);
}
}
/****************
* Put new entries from the pubrings into the trustdb.
* This function honors the sig flags to speed up the check.
*/
void
update_trustdb( )
{
KBNODE keyblock = NULL;
KBPOS kbpos;
int rc;
rc = enum_keyblocks( 0, &kbpos, &keyblock );
if( !rc ) {
ulong count=0, upd_count=0, err_count=0, new_count=0;
while( !(rc = enum_keyblocks( 1, &kbpos, &keyblock )) ) {
int modified;
rc = update_trust_record( keyblock, 1, &modified );
if( rc == -1 ) { /* not yet in trustdb: insert */
PKT_public_key *pk =
find_kbnode( keyblock, PKT_PUBLIC_KEY
) ->pkt->pkt.public_key;
rc = insert_trust_record( pk );
if( rc && !pk->local_id ) {
log_error(_("lid ?: insert failed: %s\n"),
g10_errstr(rc) );
err_count++;
}
else if( rc ) {
log_error(_("lid %lu: insert failed: %s\n"),
pk->local_id, g10_errstr(rc) );
err_count++;
}
else {
if( opt.verbose )
log_info(_("lid %lu: inserted\n"), pk->local_id );
new_count++;
}
}
else if( rc ) {
log_error(_("lid %lu: update failed: %s\n"),
lid_from_keyblock(keyblock), g10_errstr(rc) );
err_count++;
}
else if( modified ) {
if( opt.verbose )
log_info(_("lid %lu: updated\n"), lid_from_keyblock(keyblock));
upd_count++;
}
else if( opt.verbose > 1 )
log_info(_("lid %lu: okay\n"), lid_from_keyblock(keyblock) );
release_kbnode( keyblock ); keyblock = NULL;
if( !(++count % 100) )
log_info(_("%lu keys so far processed\n"), count);
}
log_info(_("%lu keys processed\n"), count);
if( err_count )
log_info(_("\t%lu keys with errors\n"), err_count);
if( upd_count )
log_info(_("\t%lu keys updated\n"), upd_count);
if( new_count )
log_info(_("\t%lu keys inserted\n"), new_count);
}
if( rc && rc != -1 )
log_error(_("enumerate keyblocks failed: %s\n"), g10_errstr(rc));
enum_keyblocks( 2, &kbpos, &keyblock ); /* close */
release_kbnode( keyblock );
}
/****************
* Get the trustlevel for this PK.
* Note: This does not ask any questions
* Returns: 0 okay of an errorcode
*
* It operates this way:
* locate the pk in the trustdb
* found:
* Do we have a valid cache record for it?
* yes: return trustlevel from cache
* no: make a cache record and all the other stuff
* not found:
* try to insert the pubkey into the trustdb and check again
*
* Problems: How do we get the complete keyblock to check that the
* cache record is actually valid? Think we need a clever
* cache in getkey.c to keep track of this stuff. Maybe it
* is not necessary to check this if we use a local pubring. Hmmmm.
*/
int
check_trust( PKT_public_key *pk, unsigned *r_trustlevel )
{
TRUSTREC rec;
unsigned trustlevel = TRUST_UNKNOWN;
int rc=0;
u32 cur_time;
u32 keyid[2];
keyid_from_pk( pk, keyid );
/* get the pubkey record */
if( pk->local_id ) {
read_record( pk->local_id, &rec, RECTYPE_DIR );
}
else { /* no local_id: scan the trustdb */
if( (rc=tdbio_search_dir_bypk( pk, &rec )) && rc != -1 ) {
log_error(_("check_trust: search dir record failed: %s\n"),
g10_errstr(rc));
return rc;
}
else if( rc == -1 ) { /* not found - insert */
rc = insert_trust_record( pk );
if( rc ) {
log_error(_("key %08lX: insert trust record failed: %s\n"),
(ulong)keyid[1], g10_errstr(rc));
goto leave;
}
log_info(_("key %08lX.%lu: inserted into trustdb\n"),
(ulong)keyid[1], pk->local_id );
/* and re-read the dir record */
read_record( pk->local_id, &rec, RECTYPE_DIR );
}
}
cur_time = make_timestamp();
if( pk->timestamp > cur_time ) {
log_info(_("key %08lX.%lu: created in future "
"(time warp or clock problem)\n"),
(ulong)keyid[1], pk->local_id );
return G10ERR_TIME_CONFLICT;
}
if( pk->expiredate && pk->expiredate <= cur_time ) {
log_info(_("key %08lX.%lu: expired at %s\n"),
(ulong)keyid[1], pk->local_id,
asctimestamp( pk->expiredate) );
trustlevel = TRUST_EXPIRED;
}
else {
rc = do_check( &rec, &trustlevel );
if( rc ) {
log_error(_("key %08lX.%lu: trust check failed: %s\n"),
(ulong)keyid[1], pk->local_id, g10_errstr(rc));
return rc;
}
}
leave:
if( DBG_TRUST )
log_debug("check_trust() returns trustlevel %04x.\n", trustlevel);
*r_trustlevel = trustlevel;
return 0;
}
int
query_trust_info( PKT_public_key *pk )
{
unsigned trustlevel;
int c;
if( check_trust( pk, &trustlevel ) )
return '?';
if( trustlevel & TRUST_FLAG_REVOKED )
return 'r';
c = trust_letter( (trustlevel & TRUST_MASK) );
if( !c )
c = '?';
return c;
}
/****************
* Enumerate all keys, which are needed to build all trust paths for
* the given key. This function does not return the key itself or
* the ultimate key (the last point in cerificate chain). Only
* certificate chains which ends up at an ultimately trusted key
* are listed. If ownertrust or validity is not NULL, the corresponding
* value for the returned LID is also returned in these variable(s).
*
* 1) create a void pointer and initialize it to NULL
* 2) pass this void pointer by reference to this function.
* Set lid to the key you want to enumerate and pass it by reference.
* 3) call this function as long as it does not return -1
* to indicate EOF. LID does contain the next key used to build the web
* 4) Always call this function a last time with LID set to NULL,
* so that it can free its context.
*
* Returns: -1 on EOF or the level of the returned LID
*/
int
enum_cert_paths( void **context, ulong *lid,
unsigned *ownertrust, unsigned *validity )
{
struct enum_cert_paths_ctx *ctx;
TRUST_SEG_LIST tsl;
if( !lid ) { /* release the context */
if( *context ) {
TRUST_SEG_LIST tsl2;
ctx = *context;
for(tsl = ctx->tsl_head; tsl; tsl = tsl2 ) {
tsl2 = tsl->next;
m_free( tsl );
}
*context = NULL;
}
return -1;
}
if( !*context ) {
TRUST_INFO *tmppath;
TRUSTREC rec;
if( !*lid )
return -1;
ctx = m_alloc_clear( sizeof *ctx );
*context = ctx;
/* collect the paths */
read_record( *lid, &rec, RECTYPE_DIR );
tmppath = m_alloc_clear( (opt.max_cert_depth+1)* sizeof *tmppath );
tsl = NULL;
collect_paths( 0, opt.max_cert_depth, 1, &rec, tmppath, &tsl );
m_free( tmppath );
sort_tsl_list( &tsl );
/* setup the context */
ctx->tsl_head = tsl;
ctx->tsl = ctx->tsl_head;
ctx->idx = 0;
}
else
ctx = *context;
while( ctx->tsl && ctx->idx >= ctx->tsl->pathlen ) {
ctx->tsl = ctx->tsl->next;
ctx->idx = 0;
}
tsl = ctx->tsl;
if( !tsl )
return -1; /* eof */
if( ownertrust )
*ownertrust = tsl->path[ctx->idx].otrust;
if( validity )
*validity = tsl->path[ctx->idx].trust;
*lid = tsl->path[ctx->idx].lid;
ctx->idx++;
return ctx->idx-1;
}
/****************
* Print the current path
*/
int
-enum_cert_paths_print( void **context, FILE *fp, ulong selected_lid )
+enum_cert_paths_print( void **context, FILE *fp,
+ int refresh, ulong selected_lid )
{
struct enum_cert_paths_ctx *ctx;
TRUST_SEG_LIST tsl;
if( !*context )
return;
ctx = *context;
if( !ctx->tsl )
return;
+ tsl = ctx->tsl;
if( !fp )
fp = stderr;
- print_path( ctx->tsl->pathlen, ctx->tsl->path, fp, selected_lid );
+ if( refresh ) { /* update the ownertrust and if possible the validity */
+ int i;
+ int match = tdbio_db_matches_options();
+
+ for( i = 0; i < tsl->pathlen; i++ ) {
+ TRUSTREC rec;
+
+ read_record( tsl->path[i].lid, &rec, RECTYPE_DIR );
+ tsl->path[i].otrust = rec.r.dir.ownertrust;
+ /* update validity only if we have it in the cache
+ * calculation is too time consuming */
+ if( match && (rec.r.dir.dirflags & DIRF_VALVALID)
+ && rec.r.dir.validity ) {
+ tsl->path[i].trust = rec.r.dir.validity;
+ if( rec.r.dir.dirflags & DIRF_REVOKED )
+ tsl->path[i].trust = TRUST_FLAG_REVOKED;
+ }
+ }
+ }
+
+ print_path( tsl->pathlen, tsl->path, fp, selected_lid );
}
/****************
* Return the assigned ownertrust value for the given LID
*/
unsigned
get_ownertrust( ulong lid )
{
TRUSTREC rec;
read_record( lid, &rec, RECTYPE_DIR );
return rec.r.dir.ownertrust;
}
int
get_ownertrust_info( ulong lid )
{
unsigned otrust;
int c;
otrust = get_ownertrust( lid );
c = trust_letter( (otrust & TRUST_MASK) );
if( !c )
c = '?';
return c;
}
/*
* Return an allocated buffer with the preference values for
* the key with LID and the userid which is identified by the
* HAMEHASH or the firstone if namehash is NULL. ret_n receives
* the length of the allcoated buffer. Structure of the buffer is
* a repeated sequences of 2 bytes; where the first byte describes the
* type of the preference and the second one the value. The constants
* PREFTYPE_xxxx should be used to reference a type.
*/
byte *
get_pref_data( ulong lid, const byte *namehash, size_t *ret_n )
{
TRUSTREC rec;
ulong recno;
read_record( lid, &rec, RECTYPE_DIR );
for( recno=rec.r.dir.uidlist; recno; recno = rec.r.uid.next ) {
read_record( recno, &rec, RECTYPE_UID );
if( rec.r.uid.prefrec
&& ( !namehash || !memcmp(namehash, rec.r.uid.namehash, 20) )) {
byte *buf;
/* found the correct one or the first one */
read_record( rec.r.uid.prefrec, &rec, RECTYPE_PREF );
if( rec.r.pref.next )
log_info(_("WARNING: can't yet handle long pref records\n"));
buf = m_alloc( ITEMS_PER_PREF_RECORD );
memcpy( buf, rec.r.pref.data, ITEMS_PER_PREF_RECORD );
*ret_n = ITEMS_PER_PREF_RECORD;
return buf;
}
}
return NULL;
}
/****************
* Check whether the algorithm is in one of the pref records
*/
int
is_algo_in_prefs( ulong lid, int preftype, int algo )
{
TRUSTREC rec;
ulong recno;
int i;
byte *pref;
read_record( lid, &rec, RECTYPE_DIR );
for( recno=rec.r.dir.uidlist; recno; recno = rec.r.uid.next ) {
read_record( recno, &rec, RECTYPE_UID );
if( rec.r.uid.prefrec ) {
read_record( rec.r.uid.prefrec, &rec, RECTYPE_PREF );
if( rec.r.pref.next )
log_info(_("WARNING: can't yet handle long pref records\n"));
pref = rec.r.pref.data;
for(i=0; i+1 < ITEMS_PER_PREF_RECORD; i+=2 ) {
if( pref[i] == preftype && pref[i+1] == algo )
return 1;
}
}
}
return 0;
}
static int
get_dir_record( PKT_public_key *pk, TRUSTREC *rec )
{
int rc=0;
if( pk->local_id ) {
read_record( pk->local_id, rec, RECTYPE_DIR );
}
else { /* no local_id: scan the trustdb */
if( (rc=tdbio_search_dir_bypk( pk, rec )) && rc != -1 )
log_error(_("get_dir_record: search_record failed: %s\n"),
g10_errstr(rc));
}
return rc;
}
/****************
* This function simply looks for the key in the trustdb
* and makes sure that pk->local_id is set to the correct value.
* Return: 0 = found
* -1 = not found
* other = error
*/
int
query_trust_record( PKT_public_key *pk )
{
TRUSTREC rec;
return get_dir_record( pk, &rec );
}
int
clear_trust_checked_flag( PKT_public_key *pk )
{
TRUSTREC rec;
int rc;
rc = get_dir_record( pk, &rec );
if( rc )
return rc;
/* check whether they are already reset */
if( !(rec.r.dir.dirflags & DIRF_CHECKED)
&& !(rec.r.dir.dirflags & DIRF_VALVALID) )
return 0;
/* reset the flag */
rec.r.dir.dirflags &= ~DIRF_CHECKED;
rec.r.dir.dirflags &= ~DIRF_VALVALID;
write_record( &rec );
do_sync();
return 0;
}
static void
check_hint_sig( ulong lid, KBNODE keyblock, u32 *keyid, byte *uidrec_hash,
TRUSTREC *sigrec, int sigidx, ulong hint_owner )
{
KBNODE node;
int rc, state;
byte uhash[20];
int is_selfsig;
PKT_signature *sigpkt = NULL;
TRUSTREC tmp;
u32 sigkid[2];
int revoke = 0;
if( sigrec->r.sig.sig[sigidx].flag & SIGF_CHECKED )
log_info(_("NOTE: sig rec %lu[%d] in hintlist "
"of %lu but marked as checked\n"),
sigrec->recnum, sigidx, hint_owner );
if( !(sigrec->r.sig.sig[sigidx].flag & SIGF_NOPUBKEY) )
log_info(_("NOTE: sig rec %lu[%d] in hintlist "
"of %lu but not marked\n"),
sigrec->recnum, sigidx, hint_owner );
read_record( sigrec->r.sig.sig[sigidx].lid, &tmp, 0 );
if( tmp.rectype != RECTYPE_DIR ) {
/* we need the dir record */
log_error(_("sig rec %lu[%d] in hintlist "
"of %lu does not point to a dir record\n"),
sigrec->recnum, sigidx, hint_owner );
return;
}
if( !tmp.r.dir.keylist ) {
log_error(_("lid %lu: no primary key\n"), tmp.r.dir.lid );
return;
}
read_record(tmp.r.dir.keylist, &tmp, RECTYPE_KEY );
keyid_from_fingerprint( tmp.r.key.fingerprint,
tmp.r.key.fingerprint_len, sigkid );
/* find the correct signature packet */
state = 0;
for( node=keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID ) {
PKT_user_id *uidpkt = node->pkt->pkt.user_id;
if( state )
break;
rmd160_hash_buffer( uhash, uidpkt->name, uidpkt->len );
if( !memcmp( uhash, uidrec_hash, 20 ) )
state = 1;
}
else if( state && node->pkt->pkttype == PKT_SIGNATURE ) {
sigpkt = node->pkt->pkt.signature;
if( sigpkt->keyid[0] == sigkid[0]
&& sigpkt->keyid[1] == sigkid[1]
&& ( (sigpkt->sig_class&~3) == 0x10
|| ( revoke = (sigpkt->sig_class == 0x30)) ) ) {
state = 2;
break; /* found */
}
}
}
if( !node ) {
log_info(_("lid %lu: user id not found in keyblock\n"), lid );
return ;
}
if( state != 2 ) {
log_info(_("lid %lu: user id without signature\n"), lid );
return ;
}
/* and check the sig */
rc = check_key_signature( keyblock, node, &is_selfsig );
if( is_selfsig ) {
log_error(_("lid %lu: self-signature in hintlist\n"), lid );
return;
}
/* FiXME: handling fo SIGF_REVOKED is not correct! */
if( !rc ) { /* valid signature */
if( opt.verbose )
log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
(ulong)keyid[1], lid, uhash[18], uhash[19],
(ulong)sigpkt->keyid[1],
revoke? _("Valid certificate revocation")
: _("Good certificate") );
sigrec->r.sig.sig[sigidx].flag = SIGF_CHECKED | SIGF_VALID;
if( revoke )
sigrec->r.sig.sig[sigidx].flag |= SIGF_REVOKED;
}
else if( rc == G10ERR_NO_PUBKEY ) {
log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
(ulong)keyid[1], lid, uhash[18], uhash[19],
(ulong)sigpkt->keyid[1],
_("very strange: no public key\n") );
sigrec->r.sig.sig[sigidx].flag = SIGF_NOPUBKEY;
}
else {
log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
(ulong)keyid[1], lid, uhash[18], uhash[19],
(ulong)sigpkt->keyid[1], g10_errstr(rc) );
sigrec->r.sig.sig[sigidx].flag = SIGF_CHECKED;
}
sigrec->dirty = 1;
}
/****************
* Process a hintlist.
* Fixme: this list is not anymore anchored to another
* record, so it should be put elsewehere in case of an error
*/
static void
process_hintlist( ulong hintlist, ulong hint_owner )
{
ulong hlst_rn;
int rc;
for( hlst_rn = hintlist; hlst_rn; ) {
TRUSTREC hlstrec;
int hlst_idx;
read_record( hlst_rn, &hlstrec, RECTYPE_HLST );
for( hlst_idx=0; hlst_idx < ITEMS_PER_HLST_RECORD; hlst_idx++ ) {
TRUSTREC dirrec;
TRUSTREC uidrec;
TRUSTREC tmprec;
KBNODE keyblock = NULL;
u32 keyid[2];
ulong lid;
ulong r1, r2;
lid = hlstrec.r.hlst.rnum[hlst_idx];
if( !lid )
continue;
read_record( lid, &dirrec, 0 );
/* make sure it points to a dir record:
* this should be true because it only makes sense to
* call this function if the dir record is available */
if( dirrec.rectype != RECTYPE_DIR ) {
log_error(_("hintlist %lu[%d] of %lu "
"does not point to a dir record\n"),
hlst_rn, hlst_idx, hint_owner );
continue;
}
if( !dirrec.r.dir.keylist ) {
log_error(_("lid %lu does not have a key\n"), lid );
continue;
}
/* get the keyblock */
read_record( dirrec.r.dir.keylist, &tmprec, RECTYPE_KEY );
rc = get_keyblock_byfprint( &keyblock,
tmprec.r.key.fingerprint,
tmprec.r.key.fingerprint_len );
if( rc ) {
log_error(_("lid %lu: can't get keyblock: %s\n"),
lid, g10_errstr(rc) );
continue;
}
keyid_from_fingerprint( tmprec.r.key.fingerprint,
tmprec.r.key.fingerprint_len, keyid );
/* Walk over all user ids and their signatures and check all
* the signature which are created by hint_owner */
for( r1 = dirrec.r.dir.uidlist; r1; r1 = uidrec.r.uid.next ) {
TRUSTREC sigrec;
read_record( r1, &uidrec, RECTYPE_UID );
for( r2 = uidrec.r.uid.siglist; r2; r2 = sigrec.r.sig.next ) {
int i;
read_record( r2, &sigrec, RECTYPE_SIG );
sigrec.dirty = 0;
for(i=0; i < SIGS_PER_RECORD; i++ ) {
if( !sigrec.r.sig.sig[i].lid )
continue; /* skip deleted sigs */
if( sigrec.r.sig.sig[i].lid != hint_owner )
continue; /* not for us */
/* some diagnostic messages */
/* and do the signature check */
check_hint_sig( lid, keyblock, keyid,
uidrec.r.uid.namehash,
&sigrec, i, hint_owner );
}
if( sigrec.dirty )
write_record( &sigrec );
}
}
release_kbnode( keyblock );
} /* loop over hlst entries */
/* delete this hlst record */
hlst_rn = hlstrec.r.hlst.next;
delete_record( hlstrec.recnum );
} /* loop over hintlist */
}
/****************
* Create or update shadow dir record and return the LID of the record
*/
static ulong
create_shadow_dir( PKT_signature *sig, ulong lid )
{
TRUSTREC sdir, hlst, tmphlst;
ulong recno, newlid;
int tmpidx=0; /* avoids gcc warnign - this is controlled by tmphlst */
int rc;
/* first see whether we already have such a record */
rc = tdbio_search_sdir( sig->keyid, sig->pubkey_algo, &sdir );
if( rc && rc != -1 ) {
log_error(_("tdbio_search_dir failed: %s\n"), g10_errstr(rc));
die_invalid_db();
}
if( rc == -1 ) { /* not found: create */
memset( &sdir, 0, sizeof sdir );
sdir.recnum = tdbio_new_recnum();
sdir.rectype= RECTYPE_SDIR;
sdir.r.sdir.lid = sdir.recnum;
sdir.r.sdir.keyid[0] = sig->keyid[0];
sdir.r.sdir.keyid[1] = sig->keyid[1];
sdir.r.sdir.pubkey_algo = sig->pubkey_algo;
sdir.r.sdir.hintlist = 0;
write_record( &sdir );
}
newlid = sdir.recnum;
/* Put the record number into the hintlist.
* (It is easier to use the lid and not the record number of the
* key to save some space (assuming that a signator has
* signed more than one user id - and it is easier to implement.)
*/
tmphlst.recnum = 0;
for( recno=sdir.r.sdir.hintlist; recno; recno = hlst.r.hlst.next) {
int i;
read_record( recno, &hlst, RECTYPE_HLST );
for( i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
if( !hlst.r.hlst.rnum[i] ) {
if( !tmphlst.recnum ) {
tmphlst = hlst;
tmpidx = i;
}
}
else if( hlst.r.hlst.rnum[i] == lid )
return newlid; /* the signature is already in the hintlist */
}
}
/* not yet in the hint list, write it */
if( tmphlst.recnum ) { /* we have an empty slot */
tmphlst.r.hlst.rnum[tmpidx] = lid;
write_record( &tmphlst );
}
else { /* must append a new hlst record */
memset( &hlst, 0, sizeof hlst );
hlst.recnum = tdbio_new_recnum();
hlst.rectype = RECTYPE_HLST;
hlst.r.hlst.next = sdir.r.sdir.hintlist;
hlst.r.hlst.rnum[0] = lid;
write_record( &hlst );
sdir.r.sdir.hintlist = hlst.recnum;
write_record( &sdir );
}
return newlid;
}
/****************
* This function checks the given public key and inserts or updates
* the keyrecord from the trustdb. Revocation certificates
* are handled here and the keybinding of subkeys is checked.
* Hmmm: Should we check here, that the key has at least one valid
* user ID or do we allow keys w/o user ID?
*
* keyblock points to the first node in the keyblock,
* keynode is the node with the public key to check
* (either primary or secondary), keyid is the keyid of
* the primary key, drec is the directory record and recno_list
* is a list used to keep track of visited records.
* Existing keyflags are recalculated if recheck is true.
*/
static void
upd_key_record( KBNODE keyblock, KBNODE keynode, u32 *keyid,
TRUSTREC *drec, RECNO_LIST *recno_list, int recheck )
{
TRUSTREC krec;
KBNODE node;
PKT_public_key *pk = keynode->pkt->pkt.public_key;
ulong lid = drec->recnum;
byte fpr[MAX_FINGERPRINT_LEN];
size_t fprlen;
ulong recno, newrecno;
int keybind_seen = 0;
int revoke_seen = 0;
int rc;
fingerprint_from_pk( pk, fpr, &fprlen );
/* do we already have this key? */
for( recno=drec->r.dir.keylist; recno; recno = krec.r.key.next ) {
read_record( recno, &krec, RECTYPE_KEY );
if( krec.r.key.fingerprint_len == fprlen
&& !memcmp( krec.r.key.fingerprint, fpr, fprlen ) )
break;
}
if( recno ) { /* yes */
ins_recno_list( recno_list, recno, RECTYPE_KEY );
}
else { /* no: insert this new key */
recheck = 1;
memset( &krec, 0, sizeof(krec) );
krec.rectype = RECTYPE_KEY;
krec.r.key.lid = lid;
krec.r.key.pubkey_algo = pk->pubkey_algo;
krec.r.key.fingerprint_len = fprlen;
memcpy(krec.r.key.fingerprint, fpr, fprlen );
krec.recnum = newrecno = tdbio_new_recnum();
write_record( &krec );
ins_recno_list( recno_list, newrecno, RECTYPE_KEY );
/* and put this new record at the end of the keylist */
if( !(recno=drec->r.dir.keylist) ) {
/* this is the first key */
drec->r.dir.keylist = newrecno;
drec->dirty = 1;
}
else { /* we already have a key, append the new one */
TRUSTREC save = krec;
for( ; recno; recno = krec.r.key.next )
read_record( recno, &krec, RECTYPE_KEY );
krec.r.key.next = newrecno;
write_record( &krec );
krec = save;
}
}
if( !recheck && (krec.r.key.keyflags & KEYF_CHECKED) )
return;
/* check keybindings and revocations */
krec.r.key.keyflags = 0;
if( keynode->pkt->pkttype == PKT_PUBLIC_KEY ) {
/* we assume that a primary key is always valid
* and check later whether we have a revocation */
krec.r.key.keyflags |= KEYF_CHECKED | KEYF_VALID;
}
for( node=keynode->next; node; node = node->next ) {
PKT_signature *sig;
if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
break; /* ready */
else if( node->pkt->pkttype != PKT_SIGNATURE )
continue;
sig = node->pkt->pkt.signature;
if( keyid[0] != sig->keyid[0] || keyid[1] != sig->keyid[1] )
continue; /* not a self signature */
if( sig->sig_class == 0x18 && !keybind_seen ) { /* a keybinding */
if( keynode->pkt->pkttype == PKT_PUBLIC_KEY )
continue; /* oops, not for a main key */
/* we check until we find a valid keybinding */
rc = check_key_signature( keyblock, node, NULL );
if( !rc ) {
if( opt.verbose )
log_info(_(
"key %08lX.%lu: Good subkey binding\n"),
(ulong)keyid_from_pk(pk,NULL), lid );
krec.r.key.keyflags |= KEYF_CHECKED | KEYF_VALID;
}
else {
log_info(_(
"key %08lX.%lu: Invalid subkey binding: %s\n"),
(ulong)keyid_from_pk(pk,NULL), lid, g10_errstr(rc) );
krec.r.key.keyflags |= KEYF_CHECKED;
krec.r.key.keyflags &= ~KEYF_VALID;
}
keybind_seen = 1;
}
else if( sig->sig_class == 0x20 && !revoke_seen ) {
if( keynode->pkt->pkttype == PKT_PUBLIC_SUBKEY )
continue; /* a subkey is not expected here */
/* This is a key revocation certificate: check it */
rc = check_key_signature( keyblock, node, NULL );
if( !rc ) {
if( opt.verbose )
log_info(_(
"key %08lX.%lu: Valid key revocation\n"),
(ulong)keyid_from_pk(pk,NULL), lid );
krec.r.key.keyflags |= KEYF_REVOKED;
}
else {
log_info(_(
"key %08lX.%lu: Invalid key revocation: %s\n"),
(ulong)keyid_from_pk(pk,NULL), lid, g10_errstr(rc) );
}
revoke_seen = 1;
}
else if( sig->sig_class == 0x28 && !revoke_seen ) {
if( keynode->pkt->pkttype == PKT_PUBLIC_KEY )
continue; /* a mainkey is not expected here */
/* This is a subkey revocation certificate: check it */
/* fixme: we should also check the revocation
* is newer than the key (OpenPGP) */
rc = check_key_signature( keyblock, node, NULL );
if( !rc ) {
if( opt.verbose )
log_info(_(
"key %08lX.%lu: Valid subkey revocation\n"),
(ulong)keyid_from_pk(pk,NULL), lid );
krec.r.key.keyflags |= KEYF_REVOKED;
}
else {
log_info(_(
"key %08lX.%lu: Invalid subkey binding: %s\n"),
(ulong)keyid_from_pk(pk,NULL), lid, g10_errstr(rc) );
}
revoke_seen = 1;
}
}
write_record( &krec );
}
/****************
* This function checks the given user ID and inserts or updates
* the uid record of the trustdb. Revocation certificates
* are handled here.
*
* keyblock points to the first node in the keyblock,
* uidnode is the node with the user id to check
* keyid is the keyid of
* the primary key, drec is the directory record and recno_list
* is a list used to keep track of visited records.
* Existing uidflags are recalculated if recheck is true.
*/
static void
upd_uid_record( KBNODE keyblock, KBNODE uidnode, u32 *keyid,
TRUSTREC *drec, RECNO_LIST *recno_list, int recheck )
{
ulong lid = drec->recnum;
PKT_user_id *uid = uidnode->pkt->pkt.user_id;
TRUSTREC urec;
PKT_signature *selfsig = NULL;
byte uidhash[20];
KBNODE node;
ulong recno, newrecno;
int rc;
/* see whether we already have an uid record */
rmd160_hash_buffer( uidhash, uid->name, uid->len );
for( recno=drec->r.dir.uidlist; recno; recno = urec.r.uid.next ) {
read_record( recno, &urec, RECTYPE_UID );
if( !memcmp( uidhash, urec.r.uid.namehash, 20 ) )
break;
}
if( recno ) { /* we already have this record */
ins_recno_list( recno_list, recno, RECTYPE_UID );
}
else { /* new user id */
recheck = 1;
memset( &urec, 0 , sizeof(urec) );
urec.rectype = RECTYPE_UID;
urec.r.uid.lid = drec->recnum;
memcpy(urec.r.uid.namehash, uidhash, 20 );
urec.recnum = newrecno = tdbio_new_recnum();
write_record( &urec );
ins_recno_list( recno_list, newrecno, RECTYPE_UID );
/* and put this new record at the end of the uidlist */
if( !(recno=drec->r.dir.uidlist) ) { /* this is the first uid */
drec->r.dir.uidlist = newrecno;
drec->dirty = 1;
}
else { /* we already have an uid, append it to the list */
TRUSTREC save = urec;
for( ; recno; recno = urec.r.key.next )
read_record( recno, &urec, RECTYPE_UID );
urec.r.uid.next = newrecno;
write_record( &urec );
urec = save;
}
}
if( recheck || !(urec.r.uid.uidflags & UIDF_CHECKED) ) {
/* check self signatures */
urec.r.uid.uidflags = 0;
for( node=uidnode->next; node; node = node->next ) {
PKT_signature *sig;
if( node->pkt->pkttype == PKT_USER_ID )
break; /* ready */
if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
break; /* ready */
if( node->pkt->pkttype != PKT_SIGNATURE )
continue;
sig = node->pkt->pkt.signature;
if( keyid[0] != sig->keyid[0] || keyid[1] != sig->keyid[1] )
continue; /* not a self signature */
if( (sig->sig_class&~3) == 0x10 ) { /* regular self signature */
rc = check_key_signature( keyblock, node, NULL );
if( !rc ) {
if( opt.verbose )
log_info( "uid %08lX.%lu/%02X%02X: %s\n",
(ulong)keyid[1], lid, uidhash[18], uidhash[19],
_("Good self-signature") );
urec.r.uid.uidflags |= UIDF_CHECKED | UIDF_VALID;
if( !selfsig )
selfsig = sig; /* use the first valid sig */
else if( sig->timestamp > selfsig->timestamp
&& sig->sig_class >= selfsig->sig_class )
selfsig = sig; /* but this one is newer */
}
else {
log_info( "uid %08lX/%02X%02X: %s: %s\n",
(ulong)keyid[1], uidhash[18], uidhash[19],
_("Invalid self-signature"),
g10_errstr(rc) );
urec.r.uid.uidflags |= UIDF_CHECKED;
}
}
else if( sig->sig_class == 0x30 ) { /* cert revocation */
rc = check_key_signature( keyblock, node, NULL );
if( !rc && selfsig && selfsig->timestamp > sig->timestamp ) {
log_info( "uid %08lX.%lu/%02X%02X: %s\n",
(ulong)keyid[1], lid, uidhash[18], uidhash[19],
_("Valid user ID revocation skipped "
"due to a newer self signature\n") );
}
else if( !rc ) {
if( opt.verbose )
log_info( "uid %08lX.%lu/%02X%02X: %s\n",
(ulong)keyid[1], lid, uidhash[18], uidhash[19],
_("Valid user ID revocation\n") );
urec.r.uid.uidflags |= UIDF_CHECKED | UIDF_VALID;
urec.r.uid.uidflags |= UIDF_REVOKED;
}
else {
log_info("uid %08lX/%02X%02X: %s: %s\n",
(ulong)keyid[1], uidhash[18], uidhash[19],
_("Invalid user ID revocation"),
g10_errstr(rc) );
}
}
}
write_record( &urec );
} /* end check self-signatures */
if( (urec.r.uid.uidflags & (UIDF_CHECKED|UIDF_VALID))
!= (UIDF_CHECKED|UIDF_VALID) )
return; /* user ID is not valid, so no need to check more things */
/* check the preferences */
if( selfsig )
upd_pref_record( &urec, keyid, selfsig );
/* check non-self signatures */
for( node=uidnode->next; node; node = node->next ) {
PKT_signature *sig;
if( node->pkt->pkttype == PKT_USER_ID )
break; /* ready */
if( node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
break; /* ready */
if( node->pkt->pkttype != PKT_SIGNATURE )
continue;
sig = node->pkt->pkt.signature;
if( keyid[0] == sig->keyid[0] || keyid[1] == sig->keyid[1] )
continue; /* skip self signature */
if( (sig->sig_class&~3) == 0x10 ) { /* regular certification */
upd_cert_record( keyblock, node, keyid, drec, recno_list,
recheck, &urec, uidhash, 0 );
}
else if( sig->sig_class == 0x30 ) { /* cert revocation */
upd_cert_record( keyblock, node, keyid, drec, recno_list,
recheck, &urec, uidhash, 1 );
}
} /* end check certificates */
write_record( &urec );
}
/****************
*
*
*/
static void
upd_pref_record( TRUSTREC *urec, u32 *keyid, PKT_signature *sig )
{
static struct {
sigsubpkttype_t subpkttype;
int preftype;
} ptable[] = {
{ SIGSUBPKT_PREF_SYM, PREFTYPE_SYM },
{ SIGSUBPKT_PREF_HASH, PREFTYPE_HASH },
{ SIGSUBPKT_PREF_COMPR, PREFTYPE_COMPR },
{ 0, 0 }
};
TRUSTREC prec;
ulong lid = urec->r.uid.lid ;
const byte *uidhash = urec->r.uid.namehash;
const byte *s;
size_t n;
int k, i;
ulong recno;
byte prefs_sig[200];
int n_prefs_sig = 0;
byte prefs_rec[200];
int n_prefs_rec = 0;
/* check for changed preferences */
for(k=0; ptable[k].subpkttype; k++ ) {
s = parse_sig_subpkt2( sig, ptable[k].subpkttype, &n );
if( s ) {
for( ; n; n--, s++ ) {
if( n_prefs_sig >= DIM(prefs_sig)-1 ) {
log_info("uid %08lX.%lu/%02X%02X: %s\n",
(ulong)keyid[1], lid, uidhash[18], uidhash[19],
_("Too many preferences") );
break;
}
prefs_sig[n_prefs_sig++] = ptable[k].preftype;
prefs_sig[n_prefs_sig++] = *s;
}
}
}
for( recno=urec->r.uid.prefrec; recno; recno = prec.r.pref.next ) {
read_record( recno, &prec, RECTYPE_PREF );
for(i = 0; i < ITEMS_PER_PREF_RECORD; i +=2 ) {
if( n_prefs_rec >= DIM(prefs_rec)-1 ) {
log_info("uid %08lX.%lu/%02X%02X: %s\n",
(ulong)keyid[1], lid, uidhash[18], uidhash[19],
_("Too many preference items") );
break;
}
if( prec.r.pref.data[i] ) {
prefs_rec[n_prefs_rec++] = prec.r.pref.data[i];
prefs_rec[n_prefs_rec++] = prec.r.pref.data[i+1];
}
}
}
if( n_prefs_sig == n_prefs_rec
&& !memcmp( prefs_sig, prefs_rec, n_prefs_sig ) )
return; /* not changed */
/* Preferences have changed: Delete all pref records
* This is much simpler than checking whether we have to
* do update the record at all - the record cache may care about it
*/
for( recno=urec->r.uid.prefrec; recno; recno = prec.r.pref.next ) {
read_record( recno, &prec, RECTYPE_PREF );
delete_record( recno );
}
if( n_prefs_sig > ITEMS_PER_PREF_RECORD )
log_info(_("WARNING: can't yet handle long pref records\n"));
memset( &prec, 0, sizeof prec );
prec.recnum = tdbio_new_recnum();
prec.rectype = RECTYPE_PREF;
prec.r.pref.lid = lid;
if( n_prefs_sig <= ITEMS_PER_PREF_RECORD )
memcpy( prec.r.pref.data, prefs_sig, n_prefs_sig );
else { /* need more than one pref record */
TRUSTREC tmp;
ulong nextrn;
int n = n_prefs_sig;
byte *pp = prefs_sig;
memcpy( prec.r.pref.data, pp, ITEMS_PER_PREF_RECORD );
n -= ITEMS_PER_PREF_RECORD;
pp += ITEMS_PER_PREF_RECORD;
nextrn = prec.r.pref.next = tdbio_new_recnum();
do {
memset( &tmp, 0, sizeof tmp );
tmp.recnum = nextrn;
tmp.rectype = RECTYPE_PREF;
tmp.r.pref.lid = lid;
if( n <= ITEMS_PER_PREF_RECORD ) {
memcpy( tmp.r.pref.data, pp, n );
n = 0;
}
else {
memcpy( tmp.r.pref.data, pp, ITEMS_PER_PREF_RECORD );
n -= ITEMS_PER_PREF_RECORD;
pp += ITEMS_PER_PREF_RECORD;
nextrn = tmp.r.pref.next = tdbio_new_recnum();
}
write_record( &tmp );
} while( n );
}
write_record( &prec );
urec->r.uid.prefrec = prec.recnum;
urec->dirty = 1;
}
static void
upd_cert_record( KBNODE keyblock, KBNODE signode, u32 *keyid,
TRUSTREC *drec, RECNO_LIST *recno_list, int recheck,
TRUSTREC *urec, const byte *uidhash, int revoke )
{
/* We simply insert the signature into the sig records but
* avoid duplicate ones. We do not check them here because
* there is a big chance, that we import required public keys
* later. The problem with this is that we must somewhere store
* the information about this signature (we need a record id).
* We do this by using the record type shadow dir, which will
* be converted to a dir record as soon as a new public key is
* inserted into the trustdb.
*/
ulong lid = drec->recnum;
PKT_signature *sig = signode->pkt->pkt.signature;
TRUSTREC rec;
ulong recno;
TRUSTREC delrec;
int delrecidx=0;
int newflag = 0;
ulong newlid = 0;
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
ulong pk_lid = 0;
int found_sig = 0;
int found_delrec = 0;
int rc;
delrec.recnum = 0;
/* get the LID of the pubkey of the signature under verification */
rc = get_pubkey( pk, sig->keyid );
if( !rc ) {
if( pk->local_id )
pk_lid = pk->local_id;
else {
rc = tdbio_search_dir_bypk( pk, &rec );
if( !rc )
pk_lid = rec.recnum;
else if( rc == -1 ) { /* see whether there is a sdir instead */
u32 akid[2];
keyid_from_pk( pk, akid );
rc = tdbio_search_sdir( akid, pk->pubkey_algo, &rec );
if( !rc )
pk_lid = rec.recnum;
}
}
}
free_public_key( pk ); pk = NULL;
/* Loop over all signatures just in case one is not correctly
* marked. If we see the correct signature, set a flag.
* delete duplicate signatures (should not happen but...) */
for( recno = urec->r.uid.siglist; recno; recno = rec.r.sig.next ) {
int i;
read_record( recno, &rec, RECTYPE_SIG );
for(i=0; i < SIGS_PER_RECORD; i++ ) {
TRUSTREC tmp;
if( !rec.r.sig.sig[i].lid ) {
if( !found_delrec && !delrec.recnum ) {
delrec = rec;
delrecidx = i;
found_delrec=1;
}
continue; /* skip deleted sigs */
}
if( rec.r.sig.sig[i].lid == pk_lid ) {
if( found_sig ) {
log_info( "sig %08lX.%lu/%02X%02X/%08lX: %s\n",
(ulong)keyid[1], lid, uidhash[18],
uidhash[19], (ulong)sig->keyid[1],
_("Duplicated certificate - deleted") );
rec.r.sig.sig[i].lid = 0;
rec.dirty = 1;
continue;
}
found_sig = 1;
}
if( !recheck && !revoke && (rec.r.sig.sig[i].flag & SIGF_CHECKED) )
continue; /* we already checked this signature */
if( !recheck && (rec.r.sig.sig[i].flag & SIGF_NOPUBKEY) )
continue; /* we do not have the public key */
read_record( rec.r.sig.sig[i].lid, &tmp, 0 );
if( tmp.rectype == RECTYPE_DIR ) {
/* In this case we should now be able to check the signature */
rc = check_key_signature( keyblock, signode, NULL );
if( !rc ) { /* valid signature */
if( opt.verbose )
log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
(ulong)keyid[1], lid, uidhash[18],
uidhash[19], (ulong)sig->keyid[1],
revoke? _("Valid certificate revocation")
: _("Good certificate") );
rec.r.sig.sig[i].flag = SIGF_CHECKED | SIGF_VALID;
if( revoke )
rec.r.sig.sig[i].flag |= SIGF_REVOKED;
}
else if( rc == G10ERR_NO_PUBKEY ) {
#if 0 /* fixme: For some reason this really happens? */
if( (rec.r.sig.sig[i].flag & SIGF_CHECKED) )
log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
(ulong)keyid[1], lid, uidhash[18],
uidhash[19], (ulong)sig->keyid[1],
_("Hmmm, public key lost?") );
#endif
rec.r.sig.sig[i].flag = SIGF_NOPUBKEY;
if( revoke )
rec.r.sig.sig[i].flag |= SIGF_REVOKED;
}
else {
log_info("sig %08lX.%lu/%02X%02X/%08lX: %s: %s\n",
(ulong)keyid[1], lid, uidhash[18],
uidhash[19], (ulong)sig->keyid[1],
revoke? _("Invalid certificate revocation")
: _("Invalid certificate"),
g10_errstr(rc));
rec.r.sig.sig[i].flag = SIGF_CHECKED;
if( revoke )
rec.r.sig.sig[i].flag |= SIGF_REVOKED;
}
rec.dirty = 1;
}
else if( tmp.rectype == RECTYPE_SDIR ) {
/* must check that it is the right one */
if( tmp.r.sdir.keyid[0] == sig->keyid[0]
&& tmp.r.sdir.keyid[1] == sig->keyid[1]
&& (!tmp.r.sdir.pubkey_algo
|| tmp.r.sdir.pubkey_algo == sig->pubkey_algo )) {
if( !(rec.r.sig.sig[i].flag & SIGF_NOPUBKEY) )
log_info(_("uid %08lX.%lu/%02X%02X: "
"has shadow dir %lu but is not yet marked.\n"),
(ulong)keyid[1], lid,
uidhash[18], uidhash[19], tmp.recnum );
rec.r.sig.sig[i].flag = SIGF_NOPUBKEY;
if( revoke )
rec.r.sig.sig[i].flag |= SIGF_REVOKED;
rec.dirty = 1;
/* fixme: should we verify that the record is
* in the hintlist? - This case here should anyway
* never occur */
}
}
else {
log_error(_("sig record %lu[%d] points to wrong record.\n"),
rec.r.sig.sig[i].lid, i );
die_invalid_db();
}
}
if( found_delrec && delrec.recnum ) {
delrec = rec;
found_delrec = 0; /* we only want the first one */
}
if( rec.dirty ) {
write_record( &rec );
rec.dirty = 0;
}
}
if( found_sig )
return;
/* at this point, we have verified, that the signature is not in
* our list of signatures. Add a new record with that signature
* and if the public key is there, check the signature. */
if( !pk_lid ) /* we have already seen that there is no pubkey */
rc = G10ERR_NO_PUBKEY;
else
rc = check_key_signature( keyblock, signode, NULL );
if( !rc ) { /* valid signature */
if( opt.verbose )
log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
(ulong)keyid[1], lid, uidhash[18],
uidhash[19], (ulong)sig->keyid[1],
revoke? _("Valid certificate revocation")
: _("Good certificate") );
newlid = pk_lid; /* this is the pk of the signature */
newflag = SIGF_CHECKED | SIGF_VALID;
if( revoke )
newflag |= SIGF_REVOKED;
}
else if( rc == G10ERR_NO_PUBKEY ) {
if( opt.verbose > 1 )
log_info("sig %08lX.%lu/%02X%02X/%08lX: %s\n",
(ulong)keyid[1], lid, uidhash[18],
uidhash[19], (ulong)sig->keyid[1], g10_errstr(rc) );
newlid = create_shadow_dir( sig, lid );
newflag = SIGF_NOPUBKEY;
if( revoke )
newflag |= SIGF_REVOKED;
}
else {
log_info( "sig %08lX.%lu/%02X%02X/%08lX: %s: %s\n",
(ulong)keyid[1], lid, uidhash[18], uidhash[19],
(ulong)sig->keyid[1],
revoke? _("Invalid certificate revocation")
: _("Invalid certificate"),
g10_errstr(rc));
newlid = create_shadow_dir( sig, lid );
newflag = SIGF_CHECKED;
if( revoke )
newflag |= SIGF_REVOKED;
}
if( delrec.recnum ) { /* we can reuse a deleted/unused slot */
delrec.r.sig.sig[delrecidx].lid = newlid;
delrec.r.sig.sig[delrecidx].flag= newflag;
write_record( &delrec );
}
else { /* must insert a new sig record */
TRUSTREC tmp;
memset( &tmp, 0, sizeof tmp );
tmp.recnum = tdbio_new_recnum();
tmp.rectype = RECTYPE_SIG;
tmp.r.sig.lid = lid;
tmp.r.sig.next = urec->r.uid.siglist;
tmp.r.sig.sig[0].lid = newlid;
tmp.r.sig.sig[0].flag= newflag;
write_record( &tmp );
urec->r.uid.siglist = tmp.recnum;
urec->dirty = 1;
}
}
/****************
* Update all the info from the public keyblock.
* The key must already exist in the keydb.
* This function is responsible for checking the signatures in cases
* where the public key is already available. If we do not have the public
* key, the check is done by some special code in insert_trust_record().
*/
int
update_trust_record( KBNODE keyblock, int recheck, int *modified )
{
PKT_public_key *primary_pk;
KBNODE node;
TRUSTREC drec;
TRUSTREC krec;
TRUSTREC urec;
TRUSTREC prec;
TRUSTREC helprec;
int rc = 0;
u32 keyid[2]; /* keyid of primary key */
ulong recno, lastrecno;
RECNO_LIST recno_list = NULL; /* list of verified records */
/* fixme: replace recno_list by a lookup on node->recno */
if( modified )
*modified = 0;
node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
primary_pk = node->pkt->pkt.public_key;
rc = get_dir_record( primary_pk, &drec );
if( rc )
return rc;
if( !primary_pk->local_id )
primary_pk->local_id = drec.recnum;
keyid_from_pk( primary_pk, keyid );
/* fixme: check that the keyblock has a valid structure */
rc = tdbio_begin_transaction();
if( rc )
return rc;
/* update the keys */
for( node=keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY )
upd_key_record( keyblock, node, keyid,
&drec, &recno_list, recheck );
}
/* update the user IDs */
for( node=keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_USER_ID )
upd_uid_record( keyblock, node, keyid,
&drec, &recno_list, recheck );
}
/* delete keyrecords from the trustdb which are not anymore used */
/* should we really do this, or is it better to keep them and */
/* mark as unused? */
lastrecno = 0;
for( recno=drec.r.dir.keylist; recno; recno = krec.r.key.next ) {
read_record( recno, &krec, RECTYPE_KEY );
if( !qry_recno_list( recno_list, recno, RECTYPE_KEY ) ) {
/* delete this one */
if( !lastrecno ) {
drec.r.dir.keylist = krec.r.key.next;
drec.dirty = 1;
}
else {
read_record( lastrecno, &helprec, RECTYPE_KEY );
helprec.r.key.next = krec.r.key.next;
write_record( &helprec );
}
delete_record( recno );
}
else
lastrecno = recno;
}
/* delete uid records and sig and their pref records from the
* trustdb which are not anymore used */
lastrecno = 0;
for( recno=drec.r.dir.uidlist; recno; recno = urec.r.uid.next ) {
read_record( recno, &urec, RECTYPE_UID );
if( !qry_recno_list( recno_list, recno, RECTYPE_UID ) ) {
ulong r2;
/* delete this one */
if( !lastrecno ) {
drec.r.dir.uidlist = urec.r.uid.next;
drec.dirty = 1;
}
else {
read_record( lastrecno, &helprec, RECTYPE_UID );
helprec.r.uid.next = urec.r.uid.next;
write_record( &helprec );
}
for(r2=urec.r.uid.prefrec ; r2; r2 = prec.r.pref.next ) {
read_record( r2, &prec, RECTYPE_PREF );
delete_record( r2 );
}
for(r2=urec.r.uid.siglist ; r2; r2 = helprec.r.sig.next ) {
read_record( r2, &helprec, RECTYPE_SIG );
delete_record( r2 );
}
delete_record( recno );
}
else
lastrecno = recno;
}
if( rc )
rc = tdbio_cancel_transaction();
else {
drec.r.dir.dirflags |= DIRF_CHECKED;
drec.r.dir.dirflags &= ~DIRF_VALVALID;
write_record( &drec );
if( modified && tdbio_is_dirty() )
*modified = 1;
rc = tdbio_end_transaction();
}
rel_recno_list( &recno_list );
return rc;
}
/****************
* Insert a trust record into the TrustDB
* This function assumes that the record does not yet exist.
*/
int
insert_trust_record( PKT_public_key *pk )
{
TRUSTREC dirrec;
TRUSTREC shadow;
KBNODE keyblock = NULL;
KBNODE node;
byte fingerprint[MAX_FINGERPRINT_LEN];
size_t fingerlen;
int rc = 0;
ulong hintlist = 0;
if( pk->local_id )
log_bug("pk->local_id=%lu\n", pk->local_id );
fingerprint_from_pk( pk, fingerprint, &fingerlen );
/* fixme: assert that we do not have this record.
* we can do this by searching for the primary keyid
*
* fixme: If there is no such key we should look whether one
* of the subkeys has been used to sign another key and in this case
* we got the key anyway. Because a secondary key can't be used
* without a primary key (it is needed to bind the secondary one
* to the primary one which has the user ids etc.)
*/
/* get the keyblock which has the key */
rc = get_keyblock_byfprint( &keyblock, fingerprint, fingerlen );
if( rc ) { /* that should never happen */
log_error( _("insert_trust_record: keyblock not found: %s\n"),
g10_errstr(rc) );
goto leave;
}
/* check that we used the primary key (we are little bit paranoid) */
{ PKT_public_key *a_pk;
u32 akid[2], bkid[2];
node = find_kbnode( keyblock, PKT_PUBLIC_KEY );
a_pk = node->pkt->pkt.public_key;
/* we can't use cmp_public_keys here because some parts (expiredate)
* might not be set in pk <--- but why (fixme) */
keyid_from_pk( a_pk, akid );
keyid_from_pk( pk, bkid );
if( akid[0] != bkid[0] || akid[1] != bkid[1] ) {
log_error(_("did not use primary key for insert_trust_record()\n"));
rc = G10ERR_GENERAL;
goto leave;
}
}
/* We have to look for a shadow dir record which must be reused
* as the dir record. And: check all signatures which are listed
* in the hintlist of the shadow dir record.
*/
rc = tdbio_search_sdir( pk->keyid, pk->pubkey_algo, &shadow );
if( rc && rc != -1 ) {
log_error(_("tdbio_search_dir failed: %s\n"), g10_errstr(rc));
die_invalid_db();
}
memset( &dirrec, 0, sizeof dirrec );
dirrec.rectype = RECTYPE_DIR;
if( !rc ) {
/* hey, great: this key has already signed other keys
* convert this to a real directory entry */
hintlist = shadow.r.sdir.hintlist;
dirrec.recnum = shadow.recnum;
}
else {
dirrec.recnum = tdbio_new_recnum();
}
dirrec.r.dir.lid = dirrec.recnum;
write_record( &dirrec );
/* store the LID */
pk->local_id = dirrec.r.dir.lid;
for( node=keyblock; node; node = node->next ) {
if( node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
PKT_public_key *pk = node->pkt->pkt.public_key;
pk->local_id = dirrec.r.dir.lid;
}
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
PKT_signature *sig = node->pkt->pkt.signature;
sig->local_id = dirrec.r.dir.lid;
}
}
/* and put all the other stuff into the keydb */
rc = update_trust_record( keyblock, 1, NULL );
if( !rc )
process_hintlist( hintlist, dirrec.r.dir.lid );
leave:
if( rc && hintlist )
; /* fixme: the hintlist is not anymore anchored */
release_kbnode( keyblock );
do_sync();
return rc;
}
int
update_ownertrust( ulong lid, unsigned new_trust )
{
TRUSTREC rec;
read_record( lid, &rec, RECTYPE_DIR );
rec.r.dir.ownertrust = new_trust;
write_record( &rec );
do_sync();
return 0;
}
diff --git a/g10/trustdb.h b/g10/trustdb.h
index fd92826ba..52caadb8f 100644
--- a/g10/trustdb.h
+++ b/g10/trustdb.h
@@ -1,72 +1,73 @@
/* trustdb.h - Trust database
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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_TRUSTDB_H
#define G10_TRUSTDB_H
/* Trust values must be sorted in ascending order */
#define TRUST_MASK 15
#define TRUST_UNKNOWN 0 /* o: not yet calculated */
#define TRUST_EXPIRED 1 /* e: calculation may be invalid */
#define TRUST_UNDEFINED 2 /* q: not enough information for calculation */
#define TRUST_NEVER 3 /* n: never trust this pubkey */
#define TRUST_MARGINAL 4 /* m: marginally trusted */
#define TRUST_FULLY 5 /* f: fully trusted */
#define TRUST_ULTIMATE 6 /* u: ultimately trusted */
/* trust values not covered by the mask */
#define TRUST_FLAG_REVOKED 32 /* r: revoked */
#define PREFTYPE_SYM 1
#define PREFTYPE_HASH 2
#define PREFTYPE_COMPR 3
/*-- trustdb.c --*/
void list_trustdb(const char *username);
void list_trust_path( const char *username );
void export_ownertrust(void);
void import_ownertrust(const char *fname);
void register_trusted_key( const char *string );
void check_trustdb( const char *username );
void update_trustdb( void );
int init_trustdb( int level, const char *dbname );
int check_trust( PKT_public_key *pk, unsigned *r_trustlevel );
int query_trust_info( PKT_public_key *pk );
int enum_cert_paths( void **context, ulong *lid,
unsigned *ownertrust, unsigned *validity );
-int enum_cert_paths_print( void **context, FILE *fp, ulong selected_lid );
+int enum_cert_paths_print( void **context, FILE *fp,
+ int refresh, ulong selected_lid );
unsigned get_ownertrust( ulong lid );
int get_ownertrust_info( ulong lid );
byte *get_pref_data( ulong lid, const byte *namehash, size_t *ret_n );
int is_algo_in_prefs( ulong lid, int preftype, int algo );
int keyid_from_lid( ulong lid, u32 *keyid );
ulong lid_from_keyblock( KBNODE keyblock );
int query_trust_record( PKT_public_key *pk );
int clear_trust_checked_flag( PKT_public_key *pk );
int insert_trust_record( PKT_public_key *pk );
int update_trust_record( KBNODE keyblock, int fast, int *modified );
int update_ownertrust( ulong lid, unsigned new_trust );
/*-- pkclist.c --*/
int edit_ownertrust( ulong lid, int mode );
#endif /*G10_TRUSTDB_H*/
diff --git a/g10/verify.c b/g10/verify.c
index 02cc5d003..86537d07c 100644
--- a/g10/verify.c
+++ b/g10/verify.c
@@ -1,87 +1,87 @@
/* verify.c - verify signed data
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "options.h"
#include "packet.h"
#include "errors.h"
#include "iobuf.h"
#include "keydb.h"
#include "memory.h"
#include "util.h"
#include "main.h"
#include "filter.h"
#include "ttyio.h"
#include "i18n.h"
/****************
* Assume that the input is a signature and verify it without
* generating any output. With no arguments, the signature packet
* is read from stdin (it may be a detached signature when not
* used in batch mode). If only a sigfile is given, it may be a complete
* signature or a detached signature in which case the signed stuff
* is expected from stdin. With more than 1 argument, the first should
* be a detached signature and the remaining files are the signed stuff.
*/
int
verify_signatures( int nfiles, char **files )
{
IOBUF fp;
armor_filter_context_t afx;
const char *sigfile;
int i, rc;
STRLIST sl;
sigfile = nfiles? *files : NULL;
/* open the signature file */
fp = iobuf_open(sigfile);
if( !fp ) {
log_error(_("can't open '%s'\n"), print_fname_stdin(sigfile));
return G10ERR_OPEN_FILE;
}
if( !opt.no_armor ) {
if( use_armor_filter( fp ) ) {
memset( &afx, 0, sizeof afx);
iobuf_push_filter( fp, armor_filter, &afx );
}
}
sl = NULL;
for(i=1 ; i < nfiles; i++ )
add_to_strlist( &sl, files[i] );
rc = proc_signature_packets( fp, sl, sigfile );
free_strlist(sl);
iobuf_close(fp);
return rc;
}
diff --git a/mpi/g10m.c b/mpi/g10m.c
index 3100ea3a2..eb9c9bedc 100644
--- a/mpi/g10m.c
+++ b/mpi/g10m.c
@@ -1,95 +1,95 @@
/* g10m.c - Wrapper for MPI
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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"
#define _g10lib_INTERNAL 1
#include "g10lib.h"
const char *g10m_revision_string(int dummy) { return "$Revision$"; }
MPI
g10m_new( unsigned nbits )
{
return mpi_alloc( (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB );
}
MPI
g10m_new_secure( unsigned nbits )
{
return mpi_alloc_secure( (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB );
}
void
g10m_release( MPI a )
{
mpi_free(a);
}
void
g10m_resize( MPI a, unsigned nbits )
{
mpi_resize( a, (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB );
}
MPI g10m_copy( MPI a ) { return mpi_copy( a ); }
void g10m_swap( MPI a, MPI b) { mpi_swap( a, b ); }
void g10m_set( MPI w, MPI u) { mpi_set( w, u ); }
void g10m_set_ui( MPI w, ulong u ) { mpi_set_ui( w, u ); }
int g10m_cmp( MPI u, MPI v ) { return mpi_cmp( u, v ); }
int g10m_cmp_ui( MPI u, ulong v ) { return mpi_cmp_ui( u, v ); }
void g10m_add(MPI w, MPI u, MPI v) { mpi_add( w, u, v ); }
void g10m_add_ui(MPI w, MPI u, ulong v ) { mpi_add_ui( w, u, v ); }
void g10m_sub( MPI w, MPI u, MPI v) { mpi_sub( w, u, v ); }
void g10m_sub_ui(MPI w, MPI u, ulong v ) { mpi_sub_ui( w, u, v ); }
void g10m_mul( MPI w, MPI u, MPI v) { mpi_mul( w, u, v ); }
void g10m_mulm( MPI w, MPI u, MPI v, MPI m) { mpi_mulm( w, u, v, m ); }
void g10m_mul_2exp( MPI w, MPI u, ulong cnt) { mpi_mul_2exp( w, u, cnt ); }
void g10m_mul_ui(MPI w, MPI u, ulong v ) { mpi_mul_ui( w, u, v ); }
void g10m_fdiv_q( MPI q, MPI d, MPI r ) { mpi_fdiv_q( q, d, r ); }
void g10m_powm( MPI r, MPI b, MPI e, MPI m) { mpi_powm( r, b, e, m ); }
int g10m_gcd( MPI g, MPI a, MPI b ) { return mpi_gcd( g, a, b ); }
int g10m_invm( MPI x, MPI u, MPI v ) { mpi_invm( x, u, v ); return 0; }
unsigned g10m_get_nbits( MPI a ) { return mpi_get_nbits( a ); }
unsigned
g10m_get_size( MPI a )
{
return mpi_get_nlimbs( a ) * BITS_PER_MPI_LIMB;
}
void
g10m_set_buffer( MPI a, const char *buffer, unsigned nbytes, int sign )
{
mpi_set_buffer( a, buffer, nbytes, sign );
}
diff --git a/mpi/mpi-add.c b/mpi/mpi-add.c
index 9e70316e0..3dd22eb0e 100644
--- a/mpi/mpi-add.c
+++ b/mpi/mpi-add.c
@@ -1,247 +1,247 @@
/* mpi-add.c - MPI functions
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1994, 1996 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
* The GNU MP Library itself is published under the LGPL;
* however I decided to publish this code under the plain GPL.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include "mpi-internal.h"
/****************
* Add the unsigned integer V to the mpi-integer U and store the
* result in W. U and V may be the same.
*/
void
mpi_add_ui(MPI w, MPI u, unsigned long v )
{
mpi_ptr_t wp, up;
mpi_size_t usize, wsize;
int usign, wsign;
usize = u->nlimbs;
usign = u->sign;
wsign = 0;
/* If not space for W (and possible carry), increase space. */
wsize = usize + 1;
if( w->alloced < wsize )
mpi_resize(w, wsize);
/* These must be after realloc (U may be the same as W). */
up = u->d;
wp = w->d;
if( !usize ) { /* simple */
wp[0] = v;
wsize = v? 1:0;
}
else if( !usign ) { /* mpi is not negative */
mpi_limb_t cy;
cy = mpihelp_add_1(wp, up, usize, v);
wp[usize] = cy;
wsize = usize + cy;
}
else { /* The signs are different. Need exact comparison to determine
* which operand to subtract from which. */
if( usize == 1 && up[0] < v ) {
wp[0] = v - up[0];
wsize = 1;
}
else {
mpihelp_sub_1(wp, up, usize, v);
/* Size can decrease with at most one limb. */
wsize = usize - (wp[usize-1]==0);
wsign = 1;
}
}
w->nlimbs = wsize;
w->sign = wsign;
}
void
mpi_add(MPI w, MPI u, MPI v)
{
mpi_ptr_t wp, up, vp;
mpi_size_t usize, vsize, wsize;
int usign, vsign, wsign;
if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */
usize = v->nlimbs;
usign = v->sign;
vsize = u->nlimbs;
vsign = u->sign;
wsize = usize + 1;
RESIZE_IF_NEEDED(w, wsize);
/* These must be after realloc (u or v may be the same as w). */
up = v->d;
vp = u->d;
}
else {
usize = u->nlimbs;
usign = u->sign;
vsize = v->nlimbs;
vsign = v->sign;
wsize = usize + 1;
RESIZE_IF_NEEDED(w, wsize);
/* These must be after realloc (u or v may be the same as w). */
up = u->d;
vp = v->d;
}
wp = w->d;
wsign = 0;
if( !vsize ) { /* simple */
MPN_COPY(wp, up, usize );
wsize = usize;
wsign = usign;
}
else if( usign != vsign ) { /* different sign */
/* This test is right since USIZE >= VSIZE */
if( usize != vsize ) {
mpihelp_sub(wp, up, usize, vp, vsize);
wsize = usize;
MPN_NORMALIZE(wp, wsize);
wsign = usign;
}
else if( mpihelp_cmp(up, vp, usize) < 0 ) {
mpihelp_sub_n(wp, vp, up, usize);
wsize = usize;
MPN_NORMALIZE(wp, wsize);
if( !usign )
wsign = 1;
}
else {
mpihelp_sub_n(wp, up, vp, usize);
wsize = usize;
MPN_NORMALIZE(wp, wsize);
if( usign )
wsign = 1;
}
}
else { /* U and V have same sign. Add them. */
mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize);
wp[usize] = cy;
wsize = usize + cy;
if( usign )
wsign = 1;
}
w->nlimbs = wsize;
w->sign = wsign;
}
/****************
* Subtract the unsigned integer V from the mpi-integer U and store the
* result in W.
*/
void
mpi_sub_ui(MPI w, MPI u, unsigned long v )
{
mpi_ptr_t wp, up;
mpi_size_t usize, wsize;
int usign, wsign;
usize = u->nlimbs;
usign = u->sign;
wsign = 0;
/* If not space for W (and possible carry), increase space. */
wsize = usize + 1;
if( w->alloced < wsize )
mpi_resize(w, wsize);
/* These must be after realloc (U may be the same as W). */
up = u->d;
wp = w->d;
if( !usize ) { /* simple */
wp[0] = v;
wsize = v? 1:0;
wsign = 1;
}
else if( usign ) { /* mpi and v are negative */
mpi_limb_t cy;
cy = mpihelp_add_1(wp, up, usize, v);
wp[usize] = cy;
wsize = usize + cy;
}
else { /* The signs are different. Need exact comparison to determine
* which operand to subtract from which. */
if( usize == 1 && up[0] < v ) {
wp[0] = v - up[0];
wsize = 1;
wsign = 1;
}
else {
mpihelp_sub_1(wp, up, usize, v);
/* Size can decrease with at most one limb. */
wsize = usize - (wp[usize-1]==0);
}
}
w->nlimbs = wsize;
w->sign = wsign;
}
void
mpi_sub(MPI w, MPI u, MPI v)
{
if( w == v ) {
MPI vv = mpi_copy(v);
vv->sign = !vv->sign;
mpi_add( w, u, vv );
mpi_free(vv);
}
else {
/* fixme: this is not thread-save (we temp. modify v) */
v->sign = !v->sign;
mpi_add( w, u, v );
v->sign = !v->sign;
}
}
void
mpi_addm( MPI w, MPI u, MPI v, MPI m)
{
mpi_add(w, u, v);
mpi_fdiv_r( w, w, m );
}
void
mpi_subm( MPI w, MPI u, MPI v, MPI m)
{
mpi_sub(w, u, v);
mpi_fdiv_r( w, w, m );
}
diff --git a/mpi/mpi-bit.c b/mpi/mpi-bit.c
index f60d5e3b9..8ca5c57dd 100644
--- a/mpi/mpi-bit.c
+++ b/mpi/mpi-bit.c
@@ -1,201 +1,201 @@
/* mpi-bit.c - MPI bit level fucntions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "mpi-internal.h"
#include "longlong.h"
#ifdef MPI_INTERNAL_NEED_CLZ_TAB
#ifdef __STDC__
const
#endif
unsigned char
__clz_tab[] =
{
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
};
#endif
#define A_LIMB_1 ((mpi_limb_t)1)
/****************
* Return the number of bits in A.
*/
unsigned
mpi_get_nbits( MPI a )
{
unsigned n;
if( mpi_is_protected(a) ) {
n = mpi_get_nbit_info(a);
if( !n )
n = a->nlimbs * BITS_PER_MPI_LIMB;
return n;
}
if( a->nlimbs ) {
mpi_limb_t alimb = a->d[a->nlimbs-1];
if( alimb )
count_leading_zeros( n, alimb );
else
n = BITS_PER_MPI_LIMB;
n = BITS_PER_MPI_LIMB - n + (a->nlimbs-1) * BITS_PER_MPI_LIMB;
}
else
n = 0;
return n;
}
/****************
* Test whether bit N is set.
*/
int
mpi_test_bit( MPI a, unsigned n )
{
unsigned limbno, bitno;
mpi_limb_t limb;
limbno = n / BITS_PER_MPI_LIMB;
bitno = n % BITS_PER_MPI_LIMB;
if( limbno >= a->nlimbs )
return 0; /* too far left: this is a 0 */
limb = a->d[limbno];
return (limb & (A_LIMB_1 << bitno))? 1: 0;
}
/****************
* Set bit N of A.
*/
void
mpi_set_bit( MPI a, unsigned n )
{
unsigned limbno, bitno;
limbno = n / BITS_PER_MPI_LIMB;
bitno = n % BITS_PER_MPI_LIMB;
if( limbno >= a->nlimbs ) { /* resize */
if( a->alloced >= limbno )
mpi_resize(a, limbno+1 );
a->nlimbs = limbno+1;
}
a->d[limbno] |= (A_LIMB_1<<bitno);
}
/****************
* Set bit N of A. and clear all bits above
*/
void
mpi_set_highbit( MPI a, unsigned n )
{
unsigned limbno, bitno;
limbno = n / BITS_PER_MPI_LIMB;
bitno = n % BITS_PER_MPI_LIMB;
if( limbno >= a->nlimbs ) { /* resize */
if( a->alloced >= limbno )
mpi_resize(a, limbno+1 );
a->nlimbs = limbno+1;
}
a->d[limbno] |= (A_LIMB_1<<bitno);
for( bitno++; bitno < BITS_PER_MPI_LIMB; bitno++ )
a->d[limbno] &= ~(A_LIMB_1 << bitno);
a->nlimbs = limbno+1;
}
/****************
* clear bit N of A and all bits above
*/
void
mpi_clear_highbit( MPI a, unsigned n )
{
unsigned limbno, bitno;
limbno = n / BITS_PER_MPI_LIMB;
bitno = n % BITS_PER_MPI_LIMB;
if( limbno >= a->nlimbs )
return; /* not allocated, so need to clear bits :-) */
for( ; bitno < BITS_PER_MPI_LIMB; bitno++ )
a->d[limbno] &= ~(A_LIMB_1 << bitno);
a->nlimbs = limbno+1;
}
/****************
* Clear bit N of A.
*/
void
mpi_clear_bit( MPI a, unsigned n )
{
unsigned limbno, bitno;
limbno = n / BITS_PER_MPI_LIMB;
bitno = n % BITS_PER_MPI_LIMB;
if( limbno >= a->nlimbs )
return; /* don't need to clear this bit, it's to far to left */
a->d[limbno] &= ~(A_LIMB_1 << bitno);
}
/****************
* Shift A by N bits to the right
* FIXME: should use alloc_limb if X and A are same.
*/
void
mpi_rshift( MPI x, MPI a, unsigned n )
{
mpi_ptr_t xp;
mpi_size_t xsize;
xsize = a->nlimbs;
x->sign = a->sign;
RESIZE_IF_NEEDED(x, xsize);
xp = x->d;
if( xsize ) {
mpihelp_rshift( xp, a->d, xsize, n);
MPN_NORMALIZE( xp, xsize);
}
x->nlimbs = xsize;
}
diff --git a/mpi/mpi-cmp.c b/mpi/mpi-cmp.c
index 7d4c8330a..f4dd70e90 100644
--- a/mpi/mpi-cmp.c
+++ b/mpi/mpi-cmp.c
@@ -1,72 +1,72 @@
/* mpi-cmp.c - MPI functions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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-internal.h"
int
mpi_cmp_ui( MPI u, unsigned long v )
{
mpi_limb_t limb = v;
if( !u->nlimbs && !limb )
return 0;
if( u->sign )
return -1;
if( u->nlimbs > 1 )
return 1;
if( u->d[0] == limb )
return 0;
else if( u->d[0] > limb )
return 1;
else
return -1;
}
int
mpi_cmp( MPI u, MPI v )
{
mpi_size_t usize = u->nlimbs;
mpi_size_t vsize = v->nlimbs;
int cmp;
/* FIXME: are the numbers always normalized? */
if( !u->sign && v->sign )
return 1;
else if( u->sign && !v->sign )
return -1;
else if( usize != vsize && !u->sign && !v->sign )
return usize - vsize;
else if( usize != vsize && u->sign && v->sign )
return vsize + usize;
else if( !usize )
return 0;
else if( !(cmp=mpihelp_cmp( u->d, v->d, usize )) )
return 0;
else if( (cmp < 0?1:0) == (u->sign?1:0))
return 1;
else
return -1;
}
diff --git a/mpi/mpi-div.c b/mpi/mpi-div.c
index b5f5809f1..6e50456d4 100644
--- a/mpi/mpi-div.c
+++ b/mpi/mpi-div.c
@@ -1,322 +1,322 @@
/* mpi-div.c - MPI functions
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1994, 1996 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
* The GNU MP Library itself is published under the LGPL;
* however I decided to publish this code under the plain GPL.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include "mpi-internal.h"
#include "longlong.h"
void
mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor )
{
int divisor_sign = divisor->sign;
MPI temp_divisor = NULL;
/* We need the original value of the divisor after the remainder has been
* preliminary calculated. We have to copy it to temporary space if it's
* the same variable as REM. */
if( rem == divisor ) {
temp_divisor = mpi_copy( divisor );
divisor = temp_divisor;
}
mpi_tdiv_r( rem, dividend, divisor );
if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs )
mpi_add( rem, rem, divisor);
if( temp_divisor )
mpi_free(temp_divisor);
}
/****************
* Division rounding the quotient towards -infinity.
* The remainder gets the same sign as the denominator.
* rem is optional
*/
ulong
mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor )
{
mpi_limb_t rlimb;
rlimb = mpihelp_mod_1( dividend->d, dividend->nlimbs, divisor );
if( rlimb && dividend->sign )
rlimb = divisor - rlimb;
if( rem ) {
rem->d[0] = rlimb;
rem->nlimbs = rlimb? 1:0;
}
return rlimb;
}
void
mpi_fdiv_q( MPI quot, MPI dividend, MPI divisor )
{
MPI tmp = mpi_alloc( mpi_get_nlimbs(quot) );
mpi_fdiv_qr( quot, tmp, dividend, divisor);
mpi_free(tmp);
}
void
mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor )
{
int divisor_sign = divisor->sign;
MPI temp_divisor = NULL;
if( quot == divisor || rem == divisor ) {
temp_divisor = mpi_copy( divisor );
divisor = temp_divisor;
}
mpi_tdiv_qr( quot, rem, dividend, divisor );
if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) {
mpi_sub_ui( quot, quot, 1 );
mpi_add( rem, rem, divisor);
}
if( temp_divisor )
mpi_free(temp_divisor);
}
/* If den == quot, den needs temporary storage.
* If den == rem, den needs temporary storage.
* If num == quot, num needs temporary storage.
* If den has temporary storage, it can be normalized while being copied,
* i.e no extra storage should be allocated.
*/
void
mpi_tdiv_r( MPI rem, MPI num, MPI den)
{
mpi_tdiv_qr(NULL, rem, num, den );
}
void
mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
{
mpi_ptr_t np, dp;
mpi_ptr_t qp, rp;
mpi_size_t nsize = num->nlimbs;
mpi_size_t dsize = den->nlimbs;
mpi_size_t qsize, rsize;
mpi_size_t sign_remainder = num->sign;
mpi_size_t sign_quotient = num->sign ^ den->sign;
unsigned normalization_steps;
mpi_limb_t q_limb;
mpi_ptr_t marker[5];
int markidx=0;
/* Ensure space is enough for quotient and remainder.
* We need space for an extra limb in the remainder, because it's
* up-shifted (normalized) below. */
rsize = nsize + 1;
mpi_resize( rem, rsize);
qsize = rsize - dsize; /* qsize cannot be bigger than this. */
if( qsize <= 0 ) {
if( num != rem ) {
rem->nlimbs = num->nlimbs;
rem->sign = num->sign;
MPN_COPY(rem->d, num->d, nsize);
}
if( quot ) {
/* This needs to follow the assignment to rem, in case the
* numerator and quotient are the same. */
quot->nlimbs = 0;
quot->sign = 0;
}
return;
}
if( quot )
mpi_resize( quot, qsize);
/* Read pointers here, when reallocation is finished. */
np = num->d;
dp = den->d;
rp = rem->d;
/* Optimize division by a single-limb divisor. */
if( dsize == 1 ) {
mpi_limb_t rlimb;
if( quot ) {
qp = quot->d;
rlimb = mpihelp_divmod_1( qp, np, nsize, dp[0] );
qsize -= qp[qsize - 1] == 0;
quot->nlimbs = qsize;
quot->sign = sign_quotient;
}
else
rlimb = mpihelp_mod_1( np, nsize, dp[0] );
rp[0] = rlimb;
rsize = rlimb != 0?1:0;
rem->nlimbs = rsize;
rem->sign = sign_remainder;
return;
}
if( quot ) {
qp = quot->d;
/* Make sure QP and NP point to different objects. Otherwise the
* numerator would be gradually overwritten by the quotient limbs. */
if(qp == np) { /* Copy NP object to temporary space. */
np = marker[markidx++] = mpi_alloc_limb_space(nsize,
mpi_is_secure(quot));
MPN_COPY(np, qp, nsize);
}
}
else /* Put quotient at top of remainder. */
qp = rp + dsize;
count_leading_zeros( normalization_steps, dp[dsize - 1] );
/* Normalize the denominator, i.e. make its most significant bit set by
* shifting it NORMALIZATION_STEPS bits to the left. Also shift the
* numerator the same number of steps (to keep the quotient the same!).
*/
if( normalization_steps ) {
mpi_ptr_t tp;
mpi_limb_t nlimb;
/* Shift up the denominator setting the most significant bit of
* the most significant word. Use temporary storage not to clobber
* the original contents of the denominator. */
tp = marker[markidx++] = mpi_alloc_limb_space(dsize,mpi_is_secure(den));
mpihelp_lshift( tp, dp, dsize, normalization_steps );
dp = tp;
/* Shift up the numerator, possibly introducing a new most
* significant word. Move the shifted numerator in the remainder
* meanwhile. */
nlimb = mpihelp_lshift(rp, np, nsize, normalization_steps);
if( nlimb ) {
rp[nsize] = nlimb;
rsize = nsize + 1;
}
else
rsize = nsize;
}
else {
/* The denominator is already normalized, as required. Copy it to
* temporary space if it overlaps with the quotient or remainder. */
if( dp == rp || (quot && (dp == qp))) {
mpi_ptr_t tp;
tp = marker[markidx++] = mpi_alloc_limb_space(dsize, mpi_is_secure(den));
MPN_COPY( tp, dp, dsize );
dp = tp;
}
/* Move the numerator to the remainder. */
if( rp != np )
MPN_COPY(rp, np, nsize);
rsize = nsize;
}
q_limb = mpihelp_divrem( qp, 0, rp, rsize, dp, dsize );
if( quot ) {
qsize = rsize - dsize;
if(q_limb) {
qp[qsize] = q_limb;
qsize += 1;
}
quot->nlimbs = qsize;
quot->sign = sign_quotient;
}
rsize = dsize;
MPN_NORMALIZE (rp, rsize);
if( normalization_steps && rsize ) {
mpihelp_rshift(rp, rp, rsize, normalization_steps);
rsize -= rp[rsize - 1] == 0?1:0;
}
rem->nlimbs = rsize;
rem->sign = sign_remainder;
while( markidx )
mpi_free_limb_space(marker[--markidx]);
}
void
mpi_tdiv_q_2exp( MPI w, MPI u, unsigned count )
{
mpi_size_t usize, wsize;
mpi_size_t limb_cnt;
usize = u->nlimbs;
limb_cnt = count / BITS_PER_MPI_LIMB;
wsize = usize - limb_cnt;
if( limb_cnt >= usize )
w->nlimbs = 0;
else {
mpi_ptr_t wp;
mpi_ptr_t up;
RESIZE_IF_NEEDED( w, wsize );
wp = w->d;
up = u->d;
count %= BITS_PER_MPI_LIMB;
if( count ) {
mpihelp_rshift( wp, up + limb_cnt, wsize, count );
wsize -= !wp[wsize - 1];
}
else {
MPN_COPY_INCR( wp, up + limb_cnt, wsize);
}
w->nlimbs = wsize;
}
}
/****************
* Check whether dividend is divisible by divisor
* (note: divisor must fit into a limb)
*/
int
mpi_divisible_ui(MPI dividend, ulong divisor )
{
return !mpihelp_mod_1( dividend->d, dividend->nlimbs, divisor );
}
diff --git a/mpi/mpi-gcd.c b/mpi/mpi-gcd.c
index eabee63d4..226faf15a 100644
--- a/mpi/mpi-gcd.c
+++ b/mpi/mpi-gcd.c
@@ -1,54 +1,54 @@
/* mpi-gcd.c - MPI functions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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-internal.h"
/****************
* Find the greatest common divisor G of A and B.
* Return: true if this 1, false in all other cases
*/
int
mpi_gcd( MPI g, MPI xa, MPI xb )
{
MPI a, b;
a = mpi_copy(xa);
b = mpi_copy(xb);
/* TAOCP Vol II, 4.5.2, Algorithm A */
a->sign = 0;
b->sign = 0;
while( mpi_cmp_ui( b, 0 ) ) {
mpi_fdiv_r( g, a, b ); /* g used as temorary variable */
mpi_set(a,b);
mpi_set(b,g);
}
mpi_set(g, a);
mpi_free(a);
mpi_free(b);
return !mpi_cmp_ui( g, 1);
}
diff --git a/mpi/mpi-inline.h b/mpi/mpi-inline.h
index fab790551..5dc6fc0a3 100644
--- a/mpi/mpi-inline.h
+++ b/mpi/mpi-inline.h
@@ -1,126 +1,126 @@
/* mpi-inline.h - Internal to the Multi Precision Integers
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1994, 1996 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
* The GNU MP Library itself is published under the LGPL;
* however I decided to publish this code under the plain GPL.
*/
#ifndef G10_MPI_INLINE_H
#define G10_MPI_INLINE_H
extern __inline__ mpi_limb_t
mpihelp_add_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
mpi_size_t s1_size, mpi_limb_t s2_limb)
{
mpi_limb_t x;
x = *s1_ptr++;
s2_limb += x;
*res_ptr++ = s2_limb;
if( s2_limb < x ) { /* sum is less than the left operand: handle carry */
while( --s1_size ) {
x = *s1_ptr++ + 1; /* add carry */
*res_ptr++ = x; /* and store */
if( x ) /* not 0 (no overflow): we can stop */
goto leave;
}
return 1; /* return carry (size of s1 to small) */
}
leave:
if( res_ptr != s1_ptr ) { /* not the same variable */
mpi_size_t i; /* copy the rest */
for( i=0; i < s1_size-1; i++ )
res_ptr[i] = s1_ptr[i];
}
return 0; /* no carry */
}
extern __inline__ mpi_limb_t
mpihelp_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
mpi_ptr_t s2_ptr, mpi_size_t s2_size)
{
mpi_limb_t cy = 0;
if( s2_size )
cy = mpihelp_add_n( res_ptr, s1_ptr, s2_ptr, s2_size );
if( s1_size - s2_size )
cy = mpihelp_add_1( res_ptr + s2_size, s1_ptr + s2_size,
s1_size - s2_size, cy);
return cy;
}
extern __inline__ mpi_limb_t
mpihelp_sub_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
mpi_size_t s1_size, mpi_limb_t s2_limb )
{
mpi_limb_t x;
x = *s1_ptr++;
s2_limb = x - s2_limb;
*res_ptr++ = s2_limb;
if( s2_limb > x ) {
while( --s1_size ) {
x = *s1_ptr++;
*res_ptr++ = x - 1;
if( x )
goto leave;
}
return 1;
}
leave:
if( res_ptr != s1_ptr ) {
mpi_size_t i;
for( i=0; i < s1_size-1; i++ )
res_ptr[i] = s1_ptr[i];
}
return 0;
}
extern __inline__ mpi_limb_t
mpihelp_sub( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
mpi_ptr_t s2_ptr, mpi_size_t s2_size)
{
mpi_limb_t cy = 0;
if( s2_size )
cy = mpihelp_sub_n(res_ptr, s1_ptr, s2_ptr, s2_size);
if( s1_size - s2_size )
cy = mpihelp_sub_1(res_ptr + s2_size, s1_ptr + s2_size,
s1_size - s2_size, cy);
return cy;
}
#endif /*G10_MPI_INLINE_H*/
diff --git a/mpi/mpi-internal.h b/mpi/mpi-internal.h
index f0b414d2a..f73efb76c 100644
--- a/mpi/mpi-internal.h
+++ b/mpi/mpi-internal.h
@@ -1,237 +1,237 @@
/* mpi-internal.h - Internal to the Multi Precision Integers
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1994, 1996 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
* The GNU MP Library itself is published under the LGPL;
* however I decided to publish this code under the plain GPL.
*/
#ifndef G10_MPI_INTERNAL_H
#define G10_MPI_INTERNAL_H
#include "mpi.h"
/* If KARATSUBA_THRESHOLD is not already defined, define it to a
* value which is good on most machines. */
/* tested 4, 16, 32 and 64, where 16 gave the best performance when
* checking a 768 and a 1024 bit ElGamal signature.
* (wk 22.12.97) */
#ifndef KARATSUBA_THRESHOLD
#define KARATSUBA_THRESHOLD 16
#endif
/* The code can't handle KARATSUBA_THRESHOLD smaller than 2. */
#if KARATSUBA_THRESHOLD < 2
#undef KARATSUBA_THRESHOLD
#define KARATSUBA_THRESHOLD 2
#endif
typedef mpi_limb_t *mpi_ptr_t; /* pointer to a limb */
typedef int mpi_size_t; /* (must be a signed type) */
#define ABS(x) (x >= 0 ? x : -x)
#define MIN(l,o) ((l) < (o) ? (l) : (o))
#define MAX(h,i) ((h) > (i) ? (h) : (i))
#define RESIZE_IF_NEEDED(a,b) \
do { \
if( (a)->alloced < (b) ) \
mpi_resize((a), (b)); \
} while(0)
/* Copy N limbs from S to D. */
#define MPN_COPY( d, s, n) \
do { \
mpi_size_t _i; \
for( _i = 0; _i < (n); _i++ ) \
(d)[_i] = (s)[_i]; \
} while(0)
#define MPN_COPY_INCR( d, s, n) \
do { \
mpi_size_t _i; \
for( _i = 0; _i < (n); _i++ ) \
(d)[_i] = (d)[_i]; \
} while (0)
#define MPN_COPY_DECR( d, s, n ) \
do { \
mpi_size_t _i; \
for( _i = (n)-1; _i >= 0; _i--) \
(d)[_i] = (s)[_i]; \
} while(0)
/* Zero N limbs at D */
#define MPN_ZERO(d, n) \
do { \
int _i; \
for( _i = 0; _i < (n); _i++ ) \
(d)[_i] = 0; \
} while (0)
#define MPN_NORMALIZE(d, n) \
do { \
while( (n) > 0 ) { \
if( (d)[(n)-1] ) \
break; \
(n)--; \
} \
} while(0)
#define MPN_NORMALIZE_NOT_ZERO(d, n) \
do { \
for(;;) { \
if( (d)[(n)-1] ) \
break; \
(n)--; \
} \
} while(0)
#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \
do { \
if( (size) < KARATSUBA_THRESHOLD ) \
mul_n_basecase (prodp, up, vp, size); \
else \
mul_n (prodp, up, vp, size, tspace); \
} while (0);
/* Divide the two-limb number in (NH,,NL) by D, with DI being the largest
* limb not larger than (2**(2*BITS_PER_MP_LIMB))/D - (2**BITS_PER_MP_LIMB).
* If this would yield overflow, DI should be the largest possible number
* (i.e., only ones). For correct operation, the most significant bit of D
* has to be set. Put the quotient in Q and the remainder in R.
*/
#define UDIV_QRNND_PREINV(q, r, nh, nl, d, di) \
do { \
mpi_limb_t _q, _ql, _r; \
mpi_limb_t _xh, _xl; \
umul_ppmm (_q, _ql, (nh), (di)); \
_q += (nh); /* DI is 2**BITS_PER_MPI_LIMB too small */ \
umul_ppmm (_xh, _xl, _q, (d)); \
sub_ddmmss (_xh, _r, (nh), (nl), _xh, _xl); \
if( _xh ) { \
sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \
_q++; \
if( _xh) { \
sub_ddmmss (_xh, _r, _xh, _r, 0, (d)); \
_q++; \
} \
} \
if( _r >= (d) ) { \
_r -= (d); \
_q++; \
} \
(r) = _r; \
(q) = _q; \
} while (0)
/*-- mpiutil.c --*/
#ifdef M_DEBUG
#define mpi_alloc_limb_space(n,f) mpi_debug_alloc_limb_space((n),(f), M_DBGINFO( __LINE__ ) )
#define mpi_free_limb_space(n) mpi_debug_free_limb_space((n), M_DBGINFO( __LINE__ ) )
mpi_ptr_t mpi_debug_alloc_limb_space( unsigned nlimbs, int sec, const char *info );
void mpi_debug_free_limb_space( mpi_ptr_t a, const char *info );
#else
mpi_ptr_t mpi_alloc_limb_space( unsigned nlimbs, int sec );
void mpi_free_limb_space( mpi_ptr_t a );
#endif
void mpi_assign_limb_space( MPI a, mpi_ptr_t ap, unsigned nlimbs );
/*-- mpihelp-add.c --*/
mpi_limb_t mpihelp_add_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
mpi_size_t s1_size, mpi_limb_t s2_limb );
mpi_limb_t mpihelp_add_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
mpi_ptr_t s2_ptr, mpi_size_t size);
mpi_limb_t mpihelp_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
mpi_ptr_t s2_ptr, mpi_size_t s2_size);
/*-- mpihelp-sub.c --*/
mpi_limb_t mpihelp_sub_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
mpi_size_t s1_size, mpi_limb_t s2_limb );
mpi_limb_t mpihelp_sub_n( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
mpi_ptr_t s2_ptr, mpi_size_t size);
mpi_limb_t mpihelp_sub(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
mpi_ptr_t s2_ptr, mpi_size_t s2_size);
/*-- mpihelp-cmp.c --*/
int mpihelp_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size );
/*-- mpihelp-mul.c --*/
mpi_limb_t mpihelp_addmul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
mpi_size_t s1_size, mpi_limb_t s2_limb);
mpi_limb_t mpihelp_submul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
mpi_size_t s1_size, mpi_limb_t s2_limb);
void mpihelp_mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp,
mpi_size_t size);
mpi_limb_t mpihelp_mul( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize,
mpi_ptr_t vp, mpi_size_t vsize);
void mpih_sqr_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size );
void mpih_sqr_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size,
mpi_ptr_t tspace);
/*-- mpihelp-mul_1.c (or xxx/cpu/ *.S) --*/
mpi_limb_t mpihelp_mul_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
mpi_size_t s1_size, mpi_limb_t s2_limb);
/*-- mpihelp-div.c --*/
mpi_limb_t mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size,
mpi_limb_t divisor_limb);
mpi_limb_t mpihelp_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs,
mpi_ptr_t np, mpi_size_t nsize,
mpi_ptr_t dp, mpi_size_t dsize);
mpi_limb_t mpihelp_divmod_1( mpi_ptr_t quot_ptr,
mpi_ptr_t dividend_ptr, mpi_size_t dividend_size,
mpi_limb_t divisor_limb);
/*-- mpihelp-shift.c --*/
mpi_limb_t mpihelp_lshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
unsigned cnt);
mpi_limb_t mpihelp_rshift( mpi_ptr_t wp, mpi_ptr_t up, mpi_size_t usize,
unsigned cnt);
/* Define stuff for longlong.h. */
#define W_TYPE_SIZE BITS_PER_MPI_LIMB
typedef mpi_limb_t UWtype;
typedef unsigned int UHWtype;
#if defined (__GNUC__)
typedef unsigned int UQItype __attribute__ ((mode (QI)));
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef int DItype __attribute__ ((mode (DI)));
typedef unsigned int UDItype __attribute__ ((mode (DI)));
#else
typedef unsigned char UQItype;
typedef long SItype;
typedef unsigned long USItype;
#endif
#ifdef __GNUC__
#include "mpi-inline.h"
#endif
#endif /*G10_MPI_INTERNAL_H*/
diff --git a/mpi/mpi-inv.c b/mpi/mpi-inv.c
index fca609600..667571235 100644
--- a/mpi/mpi-inv.c
+++ b/mpi/mpi-inv.c
@@ -1,270 +1,270 @@
/* mpi-inv.c - MPI functions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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-internal.h"
/****************
* Calculate the multiplicative inverse X of A mod N
* That is: Find the solution x for
* 1 = (a*x) mod n
*/
void
mpi_invm( MPI x, MPI a, MPI n )
{
#if 0
MPI u, v, u1, u2, u3, v1, v2, v3, q, t1, t2, t3;
MPI ta, tb, tc;
u = mpi_copy(a);
v = mpi_copy(n);
u1 = mpi_alloc_set_ui(1);
u2 = mpi_alloc_set_ui(0);
u3 = mpi_copy(u);
v1 = mpi_alloc_set_ui(0);
v2 = mpi_alloc_set_ui(1);
v3 = mpi_copy(v);
q = mpi_alloc( mpi_get_nlimbs(u)+1 );
t1 = mpi_alloc( mpi_get_nlimbs(u)+1 );
t2 = mpi_alloc( mpi_get_nlimbs(u)+1 );
t3 = mpi_alloc( mpi_get_nlimbs(u)+1 );
while( mpi_cmp_ui( v3, 0 ) ) {
mpi_fdiv_q( q, u3, v3 );
mpi_mul(t1, v1, q); mpi_mul(t2, v2, q); mpi_mul(t3, v3, q);
mpi_sub(t1, u1, t1); mpi_sub(t2, u2, t2); mpi_sub(t3, u3, t3);
mpi_set(u1, v1); mpi_set(u2, v2); mpi_set(u3, v3);
mpi_set(v1, t1); mpi_set(v2, t2); mpi_set(v3, t3);
}
/* log_debug("result:\n");
log_mpidump("q =", q );
log_mpidump("u1=", u1);
log_mpidump("u2=", u2);
log_mpidump("u3=", u3);
log_mpidump("v1=", v1);
log_mpidump("v2=", v2); */
mpi_set(x, u1);
mpi_free(u1);
mpi_free(u2);
mpi_free(u3);
mpi_free(v1);
mpi_free(v2);
mpi_free(v3);
mpi_free(q);
mpi_free(t1);
mpi_free(t2);
mpi_free(t3);
mpi_free(u);
mpi_free(v);
#elif 0
/* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X)
* modified according to Michael Penk's solution for Exercice 35 */
/* FIXME: we can simplify this in most cases (see Knuth) */
MPI u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3;
unsigned k;
int sign;
u = mpi_copy(a);
v = mpi_copy(n);
for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) {
mpi_rshift(u, u, 1);
mpi_rshift(v, v, 1);
}
u1 = mpi_alloc_set_ui(1);
u2 = mpi_alloc_set_ui(0);
u3 = mpi_copy(u);
v1 = mpi_copy(v); /* !-- used as const 1 */
v2 = mpi_alloc( mpi_get_nlimbs(u) ); mpi_sub( v2, u1, u );
v3 = mpi_copy(v);
if( mpi_test_bit(u, 0) ) { /* u is odd */
t1 = mpi_alloc_set_ui(0);
t2 = mpi_alloc_set_ui(1); t2->sign = 1;
t3 = mpi_copy(v); t3->sign = !t3->sign;
goto Y4;
}
else {
t1 = mpi_alloc_set_ui(1);
t2 = mpi_alloc_set_ui(0);
t3 = mpi_copy(u);
}
do {
do {
if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */
mpi_add(t1, t1, v);
mpi_sub(t2, t2, u);
}
mpi_rshift(t1, t1, 1);
mpi_rshift(t2, t2, 1);
mpi_rshift(t3, t3, 1);
Y4:
;
} while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */
if( !t3->sign ) {
mpi_set(u1, t1);
mpi_set(u2, t2);
mpi_set(u3, t3);
}
else {
mpi_sub(v1, v, t1);
sign = u->sign; u->sign = !u->sign;
mpi_sub(v2, u, t2);
u->sign = sign;
sign = t3->sign; t3->sign = !t3->sign;
mpi_set(v3, t3);
t3->sign = sign;
}
mpi_sub(t1, u1, v1);
mpi_sub(t2, u2, v2);
mpi_sub(t3, u3, v3);
if( t1->sign ) {
mpi_add(t1, t1, v);
mpi_sub(t2, t2, u);
}
} while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */
/* mpi_lshift( u3, k ); */
mpi_set(x, u1);
mpi_free(u1);
mpi_free(u2);
mpi_free(u3);
mpi_free(v1);
mpi_free(v2);
mpi_free(v3);
mpi_free(t1);
mpi_free(t2);
mpi_free(t3);
#else
/* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X)
* modified according to Michael Penk's solution for Exercice 35
* with further enhancement */
MPI u, v, u1, u2=NULL, u3, v1, v2=NULL, v3, t1, t2=NULL, t3;
unsigned k;
int sign;
int odd ;
u = mpi_copy(a);
v = mpi_copy(n);
for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) {
mpi_rshift(u, u, 1);
mpi_rshift(v, v, 1);
}
odd = mpi_test_bit(v,0);
u1 = mpi_alloc_set_ui(1);
if( !odd )
u2 = mpi_alloc_set_ui(0);
u3 = mpi_copy(u);
v1 = mpi_copy(v);
if( !odd ) {
v2 = mpi_alloc( mpi_get_nlimbs(u) );
mpi_sub( v2, u1, u ); /* U is used as const 1 */
}
v3 = mpi_copy(v);
if( mpi_test_bit(u, 0) ) { /* u is odd */
t1 = mpi_alloc_set_ui(0);
if( !odd ) {
t2 = mpi_alloc_set_ui(1); t2->sign = 1;
}
t3 = mpi_copy(v); t3->sign = !t3->sign;
goto Y4;
}
else {
t1 = mpi_alloc_set_ui(1);
if( !odd )
t2 = mpi_alloc_set_ui(0);
t3 = mpi_copy(u);
}
do {
do {
if( !odd ) {
if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */
mpi_add(t1, t1, v);
mpi_sub(t2, t2, u);
}
mpi_rshift(t1, t1, 1);
mpi_rshift(t2, t2, 1);
mpi_rshift(t3, t3, 1);
}
else {
if( mpi_test_bit(t1, 0) )
mpi_add(t1, t1, v);
mpi_rshift(t1, t1, 1);
mpi_rshift(t3, t3, 1);
}
Y4:
;
} while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */
if( !t3->sign ) {
mpi_set(u1, t1);
if( !odd )
mpi_set(u2, t2);
mpi_set(u3, t3);
}
else {
mpi_sub(v1, v, t1);
sign = u->sign; u->sign = !u->sign;
if( !odd )
mpi_sub(v2, u, t2);
u->sign = sign;
sign = t3->sign; t3->sign = !t3->sign;
mpi_set(v3, t3);
t3->sign = sign;
}
mpi_sub(t1, u1, v1);
if( !odd )
mpi_sub(t2, u2, v2);
mpi_sub(t3, u3, v3);
if( t1->sign ) {
mpi_add(t1, t1, v);
if( !odd )
mpi_sub(t2, t2, u);
}
} while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */
/* mpi_lshift( u3, k ); */
mpi_set(x, u1);
mpi_free(u1);
mpi_free(v1);
mpi_free(t1);
if( !odd ) {
mpi_free(u2);
mpi_free(v2);
mpi_free(t2);
}
mpi_free(u3);
mpi_free(v3);
mpi_free(t3);
mpi_free(u);
mpi_free(v);
#endif
}
diff --git a/mpi/mpi-mpow.c b/mpi/mpi-mpow.c
index 0a7ef50e9..689a7600f 100644
--- a/mpi/mpi-mpow.c
+++ b/mpi/mpi-mpow.c
@@ -1,119 +1,119 @@
/* mpi-mpow.c - MPI functions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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-internal.h"
#include "longlong.h"
#include <assert.h>
static int
build_index( MPI *exparray, int k, int i, int t )
{
int j, bitno;
int index = 0;
bitno = t-i;
for(j=k-1; j >= 0; j-- ) {
index <<= 1;
if( mpi_test_bit( exparray[j], bitno ) )
index |= 1;
}
/*log_debug("t=%d i=%d index=%d\n", t, i, index );*/
return index;
}
/****************
* RES = (BASE[0] ^ EXP[0]) * (BASE[1] ^ EXP[1]) * ... * mod M
*/
void
mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI m)
{
int k; /* number of elements */
int t; /* bit size of largest exponent */
int i, j, idx;
MPI *G; /* table with precomputed values of size 2^k */
MPI tmp;
for(k=0; basearray[k]; k++ )
;
assert(k);
for(t=0, i=0; (tmp=exparray[i]); i++ ) {
/*log_mpidump("exp: ", tmp );*/
j = mpi_get_nbits(tmp);
if( j > t )
t = j;
}
/*log_mpidump("mod: ", m );*/
assert(i==k);
assert(t);
assert( k < 10 );
G = m_alloc_clear( (1<<k) * sizeof *G );
#if 0
/* do the precomputation */
G[0] = mpi_alloc_set_ui( 1 );
for(i=1; i < (1<<k); i++ ) {
for(j=0; j < k; j++ ) {
if( (i & (1<<j) ) ) {
if( !G[i] )
G[i] = mpi_copy( basearray[j] );
else
mpi_mulm( G[i], G[i], basearray[j], m );
}
}
if( !G[i] )
G[i] = mpi_alloc(0);
}
#endif
/* and calculate */
tmp = mpi_alloc( mpi_get_nlimbs(m)+1 );
mpi_set_ui( res, 1 );
for(i = 1; i <= t; i++ ) {
mpi_mulm(tmp, res, res, m );
idx = build_index( exparray, k, i, t );
assert( idx >= 0 && idx < (1<<k) );
if( !G[idx] ) {
if( !idx )
G[0] = mpi_alloc_set_ui( 1 );
else {
for(j=0; j < k; j++ ) {
if( (idx & (1<<j) ) ) {
if( !G[idx] )
G[idx] = mpi_copy( basearray[j] );
else
mpi_mulm( G[idx], G[idx], basearray[j], m );
}
}
if( !G[idx] )
G[idx] = mpi_alloc(0);
}
}
mpi_mulm(res, tmp, G[idx], m );
}
/* cleanup */
mpi_free(tmp);
for(i=0; i < (1<<k); i++ )
mpi_free(G[i]);
m_free(G);
}
diff --git a/mpi/mpi-mul.c b/mpi/mpi-mul.c
index 74967fa6b..df8eb2586 100644
--- a/mpi/mpi-mul.c
+++ b/mpi/mpi-mul.c
@@ -1,198 +1,198 @@
/* mpi-mul.c - MPI functions
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1994, 1996 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
* The GNU MP Library itself is published under the LGPL;
* however I decided to publish this code under the plain GPL.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include "mpi-internal.h"
void
mpi_mul_ui( MPI prod, MPI mult, unsigned long small_mult )
{
mpi_size_t size, prod_size;
mpi_ptr_t prod_ptr;
mpi_limb_t cy;
int sign;
size = mult->nlimbs;
sign = mult->sign;
if( !size || !small_mult ) {
prod->nlimbs = 0;
prod->sign = 0;
return;
}
prod_size = size + 1;
if( prod->alloced < prod_size )
mpi_resize( prod, prod_size );
prod_ptr = prod->d;
cy = mpihelp_mul_1( prod_ptr, mult->d, size, (mpi_limb_t)small_mult );
if( cy )
prod_ptr[size++] = cy;
prod->nlimbs = size;
prod->sign = sign;
}
void
mpi_mul_2exp( MPI w, MPI u, unsigned long cnt)
{
mpi_size_t usize, wsize, limb_cnt;
mpi_ptr_t wp;
mpi_limb_t wlimb;
int usign, wsign;
usize = u->nlimbs;
usign = u->sign;
if( !usize ) {
w->nlimbs = 0;
w->sign = 0;
return;
}
limb_cnt = cnt / BITS_PER_MPI_LIMB;
wsize = usize + limb_cnt + 1;
if( w->alloced < wsize )
mpi_resize(w, wsize );
wp = w->d;
wsize = usize + limb_cnt;
wsign = usign;
cnt %= BITS_PER_MPI_LIMB;
if( cnt ) {
wlimb = mpihelp_lshift( wp + limb_cnt, u->d, usize, cnt );
if( wlimb ) {
wp[wsize] = wlimb;
wsize++;
}
}
else {
MPN_COPY_DECR( wp + limb_cnt, u->d, usize );
}
/* Zero all whole limbs at low end. Do it here and not before calling
* mpn_lshift, not to lose for U == W. */
MPN_ZERO( wp, limb_cnt );
w->nlimbs = wsize;
w->sign = wsign;
}
void
mpi_mul( MPI w, MPI u, MPI v)
{
mpi_size_t usize, vsize, wsize;
mpi_ptr_t up, vp, wp;
mpi_limb_t cy;
int usign, vsign, usecure, vsecure, sign_product;
int assign_wp=0;
mpi_ptr_t tmp_limb=NULL;
if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */
usize = v->nlimbs;
usign = v->sign;
usecure = mpi_is_secure(v);
up = v->d;
vsize = u->nlimbs;
vsign = u->sign;
vsecure = mpi_is_secure(u);
vp = u->d;
}
else {
usize = u->nlimbs;
usign = u->sign;
usecure = mpi_is_secure(u);
up = u->d;
vsize = v->nlimbs;
vsign = v->sign;
vsecure = mpi_is_secure(v);
vp = v->d;
}
sign_product = usign ^ vsign;
wp = w->d;
/* Ensure W has space enough to store the result. */
wsize = usize + vsize;
if( w->alloced < wsize ) {
if( wp == up || wp == vp ) {
wp = mpi_alloc_limb_space( wsize, mpi_is_secure(w) );
assign_wp = 1;
}
else {
mpi_resize(w, wsize );
wp = w->d;
}
}
else { /* Make U and V not overlap with W. */
if( wp == up ) {
/* W and U are identical. Allocate temporary space for U. */
up = tmp_limb = mpi_alloc_limb_space( usize, usecure );
/* Is V identical too? Keep it identical with U. */
if( wp == vp )
vp = up;
/* Copy to the temporary space. */
MPN_COPY( up, wp, usize );
}
else if( wp == vp ) {
/* W and V are identical. Allocate temporary space for V. */
vp = tmp_limb = mpi_alloc_limb_space( vsize, vsecure );
/* Copy to the temporary space. */
MPN_COPY( vp, wp, vsize );
}
}
if( !vsize )
wsize = 0;
else {
cy = mpihelp_mul( wp, up, usize, vp, vsize );
wsize -= cy? 0:1;
}
if( assign_wp )
mpi_assign_limb_space( w, wp, wsize );
w->nlimbs = wsize;
w->sign = sign_product;
if( tmp_limb )
mpi_free_limb_space( tmp_limb );
}
void
mpi_mulm( MPI w, MPI u, MPI v, MPI m)
{
mpi_mul(w, u, v);
mpi_fdiv_r( w, w, m );
}
diff --git a/mpi/mpi-pow.c b/mpi/mpi-pow.c
index 24430489e..96a1218d9 100644
--- a/mpi/mpi-pow.c
+++ b/mpi/mpi-pow.c
@@ -1,281 +1,281 @@
/* mpi-pow.c - MPI functions
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1994, 1996 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
* The GNU MP Library itself is published under the LGPL;
* however I decided to publish this code under the plain GPL.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include "mpi-internal.h"
#include "longlong.h"
#include <assert.h>
/****************
* RES = BASE ^ EXP mod MOD
*/
void
mpi_powm( MPI res, MPI base, MPI exp, MPI mod)
{
mpi_ptr_t rp, ep, mp, bp;
mpi_size_t esize, msize, bsize, rsize;
int esign, msign, bsign, rsign;
int esec, msec, bsec, rsec;
mpi_size_t size;
int mod_shift_cnt;
int negative_result;
mpi_ptr_t mp_marker=NULL, bp_marker=NULL, ep_marker=NULL;
mpi_ptr_t xp_marker=NULL;
int assign_rp=0;
mpi_ptr_t tspace = NULL;
mpi_size_t tsize=0; /* to avoid compiler warning, fixme: check */
esize = exp->nlimbs;
msize = mod->nlimbs;
size = 2 * msize;
esign = exp->sign;
msign = mod->sign;
esec = mpi_is_secure(exp);
msec = mpi_is_secure(mod);
bsec = mpi_is_secure(base);
rsec = mpi_is_secure(res);
rp = res->d;
ep = exp->d;
if( !msize )
msize = 1 / msize; /* provoke a signal */
if( !esize ) {
/* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0
* depending on if MOD equals 1. */
rp[0] = 1;
res->nlimbs = (msize == 1 && mod->d[0] == 1) ? 0 : 1;
res->sign = 0;
goto leave;
}
/* Normalize MOD (i.e. make its most significant bit set) as required by
* mpn_divrem. This will make the intermediate values in the calculation
* slightly larger, but the correct result is obtained after a final
* reduction using the original MOD value. */
mp = mp_marker = mpi_alloc_limb_space(msize, msec);
count_leading_zeros( mod_shift_cnt, mod->d[msize-1] );
if( mod_shift_cnt )
mpihelp_lshift( mp, mod->d, msize, mod_shift_cnt );
else
MPN_COPY( mp, mod->d, msize );
bsize = base->nlimbs;
bsign = base->sign;
if( bsize > msize ) { /* The base is larger than the module. Reduce it. */
/* Allocate (BSIZE + 1) with space for remainder and quotient.
* (The quotient is (bsize - msize + 1) limbs.) */
bp = bp_marker = mpi_alloc_limb_space( bsize + 1, bsec );
MPN_COPY( bp, base->d, bsize );
/* We don't care about the quotient, store it above the remainder,
* at BP + MSIZE. */
mpihelp_divrem( bp + msize, 0, bp, bsize, mp, msize );
bsize = msize;
/* Canonicalize the base, since we are going to multiply with it
* quite a few times. */
MPN_NORMALIZE( bp, bsize );
}
else
bp = base->d;
if( !bsize ) {
res->nlimbs = 0;
res->sign = 0;
goto leave;
}
if( res->alloced < size ) {
/* We have to allocate more space for RES. If any of the input
* parameters are identical to RES, defer deallocation of the old
* space. */
if( rp == ep || rp == mp || rp == bp ) {
rp = mpi_alloc_limb_space( size, rsec );
assign_rp = 1;
}
else {
mpi_resize( res, size );
rp = res->d;
}
}
else { /* Make BASE, EXP and MOD not overlap with RES. */
if( rp == bp ) {
/* RES and BASE are identical. Allocate temp. space for BASE. */
assert( !bp_marker );
bp = bp_marker = mpi_alloc_limb_space( bsize, bsec );
MPN_COPY(bp, rp, bsize);
}
if( rp == ep ) {
/* RES and EXP are identical. Allocate temp. space for EXP. */
ep = ep_marker = mpi_alloc_limb_space( esize, esec );
MPN_COPY(ep, rp, esize);
}
if( rp == mp ) {
/* RES and MOD are identical. Allocate temporary space for MOD.*/
assert( !mp_marker );
mp = mp_marker = mpi_alloc_limb_space( msize, msec );
MPN_COPY(mp, rp, msize);
}
}
MPN_COPY( rp, bp, bsize );
rsize = bsize;
rsign = bsign;
{
mpi_size_t i;
mpi_ptr_t xp = xp_marker = mpi_alloc_limb_space( 2 * (msize + 1), msec );
int c;
mpi_limb_t e;
mpi_limb_t carry_limb;
negative_result = (ep[0] & 1) && base->sign;
i = esize - 1;
e = ep[i];
count_leading_zeros (c, e);
e = (e << c) << 1; /* shift the exp bits to the left, lose msb */
c = BITS_PER_MPI_LIMB - 1 - c;
/* Main loop.
*
* Make the result be pointed to alternately by XP and RP. This
* helps us avoid block copying, which would otherwise be necessary
* with the overlap restrictions of mpihelp_divmod. With 50% probability
* the result after this loop will be in the area originally pointed
* by RP (==RES->d), and with 50% probability in the area originally
* pointed to by XP.
*/
for(;;) {
while( c ) {
mpi_ptr_t tp;
mpi_size_t xsize;
/*mpihelp_mul_n(xp, rp, rp, rsize);*/
if( rsize < KARATSUBA_THRESHOLD )
mpih_sqr_n_basecase( xp, rp, rsize );
else {
if( !tspace ) {
tsize = 2 * rsize;
tspace = mpi_alloc_limb_space( tsize, 0 );
}
else if( tsize < (2*rsize) ) {
mpi_free_limb_space( tspace );
tsize = 2 * rsize;
tspace = mpi_alloc_limb_space( tsize, 0 );
}
mpih_sqr_n( xp, rp, rsize, tspace );
}
xsize = 2 * rsize;
if( xsize > msize ) {
mpihelp_divrem(xp + msize, 0, xp, xsize, mp, msize);
xsize = msize;
}
tp = rp; rp = xp; xp = tp;
rsize = xsize;
if( (mpi_limb_signed_t)e < 0 ) {
mpihelp_mul( xp, rp, rsize, bp, bsize );
xsize = rsize + bsize;
if( xsize > msize ) {
mpihelp_divrem(xp + msize, 0, xp, xsize, mp, msize);
xsize = msize;
}
tp = rp; rp = xp; xp = tp;
rsize = xsize;
}
e <<= 1;
c--;
}
i--;
if( i < 0 )
break;
e = ep[i];
c = BITS_PER_MPI_LIMB;
}
/* We shifted MOD, the modulo reduction argument, left MOD_SHIFT_CNT
* steps. Adjust the result by reducing it with the original MOD.
*
* Also make sure the result is put in RES->d (where it already
* might be, see above).
*/
if( mod_shift_cnt ) {
carry_limb = mpihelp_lshift( res->d, rp, rsize, mod_shift_cnt);
rp = res->d;
if( carry_limb ) {
rp[rsize] = carry_limb;
rsize++;
}
}
else {
MPN_COPY( res->d, rp, rsize);
rp = res->d;
}
if( rsize >= msize ) {
mpihelp_divrem(rp + msize, 0, rp, rsize, mp, msize);
rsize = msize;
}
/* Remove any leading zero words from the result. */
if( mod_shift_cnt )
mpihelp_rshift( rp, rp, rsize, mod_shift_cnt);
MPN_NORMALIZE (rp, rsize);
}
if( negative_result && rsize ) {
if( mod_shift_cnt )
mpihelp_rshift( mp, mp, msize, mod_shift_cnt);
mpihelp_sub( rp, mp, msize, rp, rsize);
rsize = msize;
rsign = msign;
MPN_NORMALIZE(rp, rsize);
}
res->nlimbs = rsize;
res->sign = rsign;
leave:
if( assign_rp ) mpi_assign_limb_space( res, rp, size );
if( mp_marker ) mpi_free_limb_space( mp_marker );
if( bp_marker ) mpi_free_limb_space( bp_marker );
if( ep_marker ) mpi_free_limb_space( ep_marker );
if( xp_marker ) mpi_free_limb_space( xp_marker );
if( tspace ) mpi_free_limb_space( tspace );
}
diff --git a/mpi/mpi-scan.c b/mpi/mpi-scan.c
index d0a3ef51e..82ac7262a 100644
--- a/mpi/mpi-scan.c
+++ b/mpi/mpi-scan.c
@@ -1,132 +1,132 @@
/* mpi-scan.c - MPI functions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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-internal.h"
#include "longlong.h"
/****************
* Scan through an mpi and return byte for byte. a -1 is returned to indicate
* the end of the mpi. Scanning is done from the lsb to the msb, returned
* values are in the range of 0 .. 255.
*
* FIXME: This code is VERY ugly!
*/
int
mpi_getbyte( MPI a, unsigned index )
{
int i, j;
unsigned n;
mpi_ptr_t ap;
mpi_limb_t limb;
ap = a->d;
for(n=0,i=0; i < a->nlimbs; i++ ) {
limb = ap[i];
for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ )
if( n == index )
return (limb >> j*8) & 0xff;
}
return -1;
}
/****************
* Put a value at position INDEX into A. index counts from lsb to msb
*/
void
mpi_putbyte( MPI a, unsigned index, int xc )
{
int i, j;
unsigned n;
mpi_ptr_t ap;
mpi_limb_t limb, c;
c = xc & 0xff;
ap = a->d;
for(n=0,i=0; i < a->alloced; i++ ) {
limb = ap[i];
for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ )
if( n == index ) {
#if BYTES_PER_MPI_LIMB == 4
if( j == 0 )
limb = (limb & 0xffffff00) | c;
else if( j == 1 )
limb = (limb & 0xffff00ff) | (c<<8);
else if( j == 2 )
limb = (limb & 0xff00ffff) | (c<<16);
else
limb = (limb & 0x00ffffff) | (c<<24);
#elif BYTES_PER_MPI_LIMB == 8
if( j == 0 )
limb = (limb & 0xffffffffffffff00) | c;
else if( j == 1 )
limb = (limb & 0xffffffffffff00ff) | (c<<8);
else if( j == 2 )
limb = (limb & 0xffffffffff00ffff) | (c<<16);
else if( j == 3 )
limb = (limb & 0xffffffff00ffffff) | (c<<24);
else if( j == 4 )
limb = (limb & 0xffffff00ffffffff) | (c<<32);
else if( j == 5 )
limb = (limb & 0xffff00ffffffffff) | (c<<40);
else if( j == 6 )
limb = (limb & 0xff00ffffffffffff) | (c<<48);
else
limb = (limb & 0x00ffffffffffffff) | (c<<56);
#else
#error please enhance this function, its ugly - i know.
#endif
if( a->nlimbs <= i )
a->nlimbs = i+1;
ap[i] = limb;
return;
}
}
abort(); /* index out of range */
}
/****************
* Count the number of zerobits at the low end of A
*/
unsigned
mpi_trailing_zeros( MPI a )
{
unsigned n, count = 0;
for(n=0; n < a->nlimbs; n++ ) {
if( a->d[n] ) {
unsigned nn;
mpi_limb_t alimb = a->d[n];
count_trailing_zeros( nn, alimb );
count += nn;
break;
}
count += BITS_PER_MPI_LIMB;
}
return count;
}
diff --git a/mpi/mpicoder.c b/mpi/mpicoder.c
index 1fab786f5..2ef4c1419 100644
--- a/mpi/mpicoder.c
+++ b/mpi/mpicoder.c
@@ -1,436 +1,436 @@
/* mpicoder.c - Coder for the external representation of MPIs
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <string.h>
#include <stdlib.h>
#include <assert.h>
#include "mpi.h"
#include "mpi-internal.h"
#include "iobuf.h"
#include "memory.h"
#include "util.h"
#ifdef M_DEBUG
#undef mpi_read
#endif
#define MAX_EXTERN_MPI_BITS 16384
/****************
* write an mpi to out.
*/
int
mpi_write( IOBUF out, MPI a )
{
int rc;
unsigned nbits = mpi_get_nbits(a);
byte *p, *buf;
unsigned n;
if( nbits > MAX_EXTERN_MPI_BITS )
log_bug("mpi_encode: mpi too large (%u bits)\n", nbits);
iobuf_put(out, (nbits >>8) );
iobuf_put(out, (nbits) );
p = buf = mpi_get_buffer( a, &n, NULL );
rc = iobuf_write( out, p, n );
m_free(buf);
return rc;
}
/****************
* Read an external representation of an mpi and return the MPI
* The external format is a 16 bit unsigned value stored in network byte order,
* giving the number of bits for the following integer. The integer is stored
* with MSB first (left padded with zeroes to align on a byte boundary).
*/
MPI
#ifdef M_DEBUG
mpi_debug_read(IOBUF inp, unsigned *ret_nread, int secure, const char *info)
#else
mpi_read(IOBUF inp, unsigned *ret_nread, int secure)
#endif
{
int c, i, j;
unsigned nbits, nbytes, nlimbs, nread=0;
mpi_limb_t a;
MPI val = MPI_NULL;
if( (c = iobuf_get(inp)) == -1 )
goto leave;
nbits = c << 8;
if( (c = iobuf_get(inp)) == -1 )
goto leave;
nbits |= c;
if( nbits > MAX_EXTERN_MPI_BITS ) {
log_error("mpi too large (%u bits)\n", nbits);
goto leave;
}
nread = 2;
nbytes = (nbits+7) / 8;
nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
#ifdef M_DEBUG
val = secure? mpi_debug_alloc_secure( nlimbs, info )
: mpi_debug_alloc( nlimbs, info );
#else
val = secure? mpi_alloc_secure( nlimbs )
: mpi_alloc( nlimbs );
#endif
i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
i %= BYTES_PER_MPI_LIMB;
val->nbits = nbits;
j= val->nlimbs = nlimbs;
val->sign = 0;
for( ; j > 0; j-- ) {
a = 0;
for(; i < BYTES_PER_MPI_LIMB; i++ ) {
a <<= 8;
a |= iobuf_get(inp) & 0xff; nread++;
}
i = 0;
val->d[j-1] = a;
}
leave:
if( nread > *ret_nread )
log_bug("mpi crosses packet border");
else
*ret_nread = nread;
return val;
}
MPI
mpi_read_from_buffer(byte *buffer, unsigned *ret_nread, int secure)
{
int i, j;
unsigned nbits, nbytes, nlimbs, nread=0;
mpi_limb_t a;
MPI val = MPI_NULL;
if( *ret_nread < 2 )
goto leave;
nbits = buffer[0] << 8 | buffer[1];
if( nbits > MAX_EXTERN_MPI_BITS ) {
log_error("mpi too large (%u bits)\n", nbits);
goto leave;
}
buffer += 2;
nread = 2;
nbytes = (nbits+7) / 8;
nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
val = secure? mpi_alloc_secure( nlimbs )
: mpi_alloc( nlimbs );
i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
i %= BYTES_PER_MPI_LIMB;
val->nbits = nbits;
j= val->nlimbs = nlimbs;
val->sign = 0;
for( ; j > 0; j-- ) {
a = 0;
for(; i < BYTES_PER_MPI_LIMB; i++ ) {
if( ++nread > *ret_nread )
log_bug("mpi larger than buffer");
a <<= 8;
a |= *buffer++;
}
i = 0;
val->d[j-1] = a;
}
leave:
*ret_nread = nread;
return val;
}
/****************
* Make an mpi from a character string.
*/
int
mpi_fromstr(MPI val, const char *str)
{
int hexmode=0, sign=0, prepend_zero=0, i, j, c, c1, c2;
unsigned nbits, nbytes, nlimbs;
mpi_limb_t a;
if( *str == '-' ) {
sign = 1;
str++;
}
if( *str == '0' && str[1] == 'x' )
hexmode = 1;
else
return 1; /* other bases are not yet supported */
str += 2;
nbits = strlen(str)*4;
if( nbits % 8 )
prepend_zero = 1;
nbytes = (nbits+7) / 8;
nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
if( val->alloced < nlimbs )
mpi_resize(val, nlimbs );
i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
i %= BYTES_PER_MPI_LIMB;
j= val->nlimbs = nlimbs;
val->sign = sign;
for( ; j > 0; j-- ) {
a = 0;
for(; i < BYTES_PER_MPI_LIMB; i++ ) {
if( prepend_zero ) {
c1 = '0';
prepend_zero = 0;
}
else
c1 = *str++;
assert(c1);
c2 = *str++;
assert(c2);
if( c1 >= '0' && c1 <= '9' )
c = c1 - '0';
else if( c1 >= 'a' && c1 <= 'f' )
c = c1 - 'a' + 10;
else if( c1 >= 'A' && c1 <= 'F' )
c = c1 - 'A' + 10;
else {
mpi_clear(val);
return 1;
}
c <<= 4;
if( c2 >= '0' && c2 <= '9' )
c |= c2 - '0';
else if( c2 >= 'a' && c2 <= 'f' )
c |= c2 - 'a' + 10;
else if( c2 >= 'A' && c2 <= 'F' )
c |= c2 - 'A' + 10;
else {
mpi_clear(val);
return 1;
}
a <<= 8;
a |= c;
}
i = 0;
val->d[j-1] = a;
}
return 0;
}
/****************
* print an MPI to the given stream and return the number of characters
* printed.
*/
int
mpi_print( FILE *fp, MPI a, int mode )
{
int i, n=0;
if( a == MPI_NULL )
return fprintf(fp, "[MPI_NULL]");
if( !mode ) {
unsigned n1, n2;
n1 = mpi_get_nbits(a);
n2 = mpi_get_nbit_info(a);
if( n2 && n2 != n1 )
n += fprintf(fp, "[%u bits (%u)]", n1, n2 );
else
n += fprintf(fp, "[%u bits]", n1);
}
else {
if( a->sign )
putc('-', fp);
#if BYTES_PER_MPI_LIMB == 2
#define X "4"
#elif BYTES_PER_MPI_LIMB == 4
#define X "8"
#elif BYTES_PER_MPI_LIMB == 8
#define X "16"
#else
#error please define the format here
#endif
for(i=a->nlimbs; i > 0 ; i-- ) {
n += fprintf(fp, i!=a->nlimbs? "%0" X "lX":"%lX", (ulong)a->d[i-1]);
#undef X
}
if( !a->nlimbs )
putc('0', fp );
}
return n;
}
/****************
* Special function to get the low 8 bytes from an mpi.
* This can be used as a keyid; KEYID is an 2 element array.
* Return the low 4 bytes.
*/
u32
mpi_get_keyid( MPI a, u32 *keyid )
{
#if BYTES_PER_MPI_LIMB == 4
if( keyid ) {
keyid[0] = a->nlimbs >= 2? a->d[1] : 0;
keyid[1] = a->nlimbs >= 1? a->d[0] : 0;
}
return a->nlimbs >= 1? a->d[0] : 0;
#elif BYTES_PER_MPI_LIMB == 8
if( keyid ) {
keyid[0] = a->nlimbs? (u32)(a->d[0] >> 32) : 0;
keyid[1] = a->nlimbs? (u32)(a->d[0] & 0xffffffff) : 0;
}
return a->nlimbs? (u32)(a->d[0] & 0xffffffff) : 0;
#else
#error Make this function work with other LIMB sizes
#endif
}
/****************
* Return an m_alloced buffer with the MPI (msb first).
* NBYTES receives the length of this buffer. Caller must free the
* return string (This function does return a 0 byte buffer with NBYTES
* set to zero if the value of A is zero. If sign is not NULL, it will
* be set to the sign of the A.
*/
static byte *
do_get_buffer( MPI a, unsigned *nbytes, int *sign, int force_secure )
{
byte *p, *buffer;
mpi_limb_t alimb;
int i;
if( sign )
*sign = a->sign;
*nbytes = a->nlimbs * BYTES_PER_MPI_LIMB;
p = buffer = force_secure || mpi_is_secure(a) ? m_alloc_secure( *nbytes)
: m_alloc( *nbytes );
for(i=a->nlimbs-1; i >= 0; i-- ) {
alimb = a->d[i];
#if BYTES_PER_MPI_LIMB == 4
*p++ = alimb >> 24;
*p++ = alimb >> 16;
*p++ = alimb >> 8;
*p++ = alimb ;
#elif BYTES_PER_MPI_LIMB == 8
*p++ = alimb >> 56;
*p++ = alimb >> 48;
*p++ = alimb >> 40;
*p++ = alimb >> 32;
*p++ = alimb >> 24;
*p++ = alimb >> 16;
*p++ = alimb >> 8;
*p++ = alimb ;
#else
#error please implement for this limb size.
#endif
}
/* this is sub-optimal but we need to do the shift oepration because
* the caller has to free the returned buffer */
for(p=buffer; !*p && *nbytes; p++, --*nbytes )
;
if( p != buffer )
memmove(buffer,p, *nbytes);
return buffer;
}
byte *
mpi_get_buffer( MPI a, unsigned *nbytes, int *sign )
{
return do_get_buffer( a, nbytes, sign, 0 );
}
byte *
mpi_get_secure_buffer( MPI a, unsigned *nbytes, int *sign )
{
return do_get_buffer( a, nbytes, sign, 1 );
}
/****************
* Use BUFFER to update MPI.
*/
void
mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign )
{
const byte *p;
mpi_limb_t alimb;
int nlimbs;
int i;
nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
RESIZE_IF_NEEDED(a, nlimbs);
a->sign = sign;
for(i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; ) {
#if BYTES_PER_MPI_LIMB == 4
alimb = *p-- ;
alimb |= *p-- << 8 ;
alimb |= *p-- << 16 ;
alimb |= *p-- << 24 ;
#elif BYTES_PER_MPI_LIMB == 8
alimb = (mpi_limb_t)*p-- ;
alimb |= (mpi_limb_t)*p-- << 8 ;
alimb |= (mpi_limb_t)*p-- << 16 ;
alimb |= (mpi_limb_t)*p-- << 24 ;
alimb |= (mpi_limb_t)*p-- << 32 ;
alimb |= (mpi_limb_t)*p-- << 40 ;
alimb |= (mpi_limb_t)*p-- << 48 ;
alimb |= (mpi_limb_t)*p-- << 56 ;
#else
#error please implement for this limb size.
#endif
a->d[i++] = alimb;
}
if( p >= buffer ) {
#if BYTES_PER_MPI_LIMB == 4
alimb = *p-- ;
if( p >= buffer ) alimb |= *p-- << 8 ;
if( p >= buffer ) alimb |= *p-- << 16 ;
if( p >= buffer ) alimb |= *p-- << 24 ;
#elif BYTES_PER_MPI_LIMB == 8
alimb = (mpi_limb_t)*p-- ;
if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 8 ;
if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 16 ;
if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 24 ;
if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 32 ;
if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 40 ;
if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 48 ;
if( p >= buffer ) alimb |= (mpi_limb_t)*p-- << 56 ;
#else
#error please implement for this limb size.
#endif
a->d[i++] = alimb;
}
a->nlimbs = i;
assert( i == nlimbs );
}
diff --git a/mpi/mpih-add.c b/mpi/mpih-add.c
index 566469c3e..d6b0c3eb0 100644
--- a/mpi/mpih-add.c
+++ b/mpi/mpih-add.c
@@ -1,88 +1,88 @@
/* mpihelp-add.c - MPI helper functions
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1994, 1996 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
* The GNU MP Library itself is published under the LGPL;
* however I decided to publish this code under the plain GPL.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include "mpi-internal.h"
/****************
* Add to S1_PTR with size S1_SIZE the limb S2_LIMB and
* store the result in RES_PTR. Return the carry
* S1_SIZE must be > 0.
*/
#ifndef __GNUC__
/*_EXTERN_INLINE */
mpi_limb_t
mpihelp_add_1( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
mpi_size_t s1_size, mpi_limb_t s2_limb)
{
mpi_limb_t x;
x = *s1_ptr++;
s2_limb += x;
*res_ptr++ = s2_limb;
if( s2_limb < x ) { /* sum is less than the left operand: handle carry */
while( --s1_size ) {
x = *s1_ptr++ + 1; /* add carry */
*res_ptr++ = x; /* and store */
if( x ) /* not 0 (no overflow): we can stop */
goto leave;
}
return 1; /* return carry (size of s1 to small) */
}
leave:
if( res_ptr != s1_ptr ) { /* not the same variable */
mpi_size_t i; /* copy the rest */
for( i=0; i < s1_size-1; i++ )
res_ptr[i] = s1_ptr[i];
}
return 0; /* no carry */
}
/*_EXTERN_INLINE*/
mpi_limb_t
mpihelp_add(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
mpi_ptr_t s2_ptr, mpi_size_t s2_size)
{
mpi_limb_t cy = 0;
if( s2_size )
cy = mpihelp_add_n( res_ptr, s1_ptr, s2_ptr, s2_size );
if( s1_size - s2_size )
cy = mpihelp_add_1( res_ptr + s2_size, s1_ptr + s2_size,
s1_size - s2_size, cy);
return cy;
}
#endif
diff --git a/mpi/mpih-cmp.c b/mpi/mpih-cmp.c
index dad993c2e..9c9cb4a6c 100644
--- a/mpi/mpih-cmp.c
+++ b/mpi/mpih-cmp.c
@@ -1,62 +1,62 @@
/* mpihelp-sub.c - MPI helper functions
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1994, 1996 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
* The GNU MP Library itself is published under the LGPL;
* however I decided to publish this code under the plain GPL.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include "mpi-internal.h"
/****************
* Compare OP1_PTR/OP1_SIZE with OP2_PTR/OP2_SIZE.
* There are no restrictions on the relative sizes of
* the two arguments.
* Return 1 if OP1 > OP2, 0 if they are equal, and -1 if OP1 < OP2.
*/
int
mpihelp_cmp( mpi_ptr_t op1_ptr, mpi_ptr_t op2_ptr, mpi_size_t size )
{
mpi_size_t i;
mpi_limb_t op1_word, op2_word;
for( i = size - 1; i >= 0 ; i--) {
op1_word = op1_ptr[i];
op2_word = op2_ptr[i];
if( op1_word != op2_word )
goto diff;
}
return 0;
diff:
/* This can *not* be simplified to
* op2_word - op2_word
* since that expression might give signed overflow. */
return (op1_word > op2_word) ? 1 : -1;
}
diff --git a/mpi/mpih-div.c b/mpi/mpih-div.c
index cda6150f1..0d711cb58 100644
--- a/mpi/mpih-div.c
+++ b/mpi/mpih-div.c
@@ -1,537 +1,537 @@
/* mpihelp-div.c - MPI helper functions
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1994, 1996 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
* The GNU MP Library itself is published under the LGPL;
* however I decided to publish this code under the plain GPL.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include "mpi-internal.h"
#include "longlong.h"
#ifndef UMUL_TIME
#define UMUL_TIME 1
#endif
#ifndef UDIV_TIME
#define UDIV_TIME UMUL_TIME
#endif
/* FIXME: We should be using invert_limb (or invert_normalized_limb)
* here (not udiv_qrnnd).
*/
mpi_limb_t
mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size,
mpi_limb_t divisor_limb)
{
mpi_size_t i;
mpi_limb_t n1, n0, r;
int dummy;
/* Botch: Should this be handled at all? Rely on callers? */
if( !dividend_size )
return 0;
/* If multiplication is much faster than division, and the
* dividend is large, pre-invert the divisor, and use
* only multiplications in the inner loop.
*
* This test should be read:
* Does it ever help to use udiv_qrnnd_preinv?
* && Does what we save compensate for the inversion overhead?
*/
if( UDIV_TIME > (2 * UMUL_TIME + 6)
&& (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) {
int normalization_steps;
count_leading_zeros( normalization_steps, divisor_limb );
if( normalization_steps ) {
mpi_limb_t divisor_limb_inverted;
divisor_limb <<= normalization_steps;
/* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The
* result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the
* most significant bit (with weight 2**N) implicit.
*
* Special case for DIVISOR_LIMB == 100...000.
*/
if( !(divisor_limb << 1) )
divisor_limb_inverted = ~(mpi_limb_t)0;
else
udiv_qrnnd(divisor_limb_inverted, dummy,
-divisor_limb, 0, divisor_limb);
n1 = dividend_ptr[dividend_size - 1];
r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps);
/* Possible optimization:
* if (r == 0
* && divisor_limb > ((n1 << normalization_steps)
* | (dividend_ptr[dividend_size - 2] >> ...)))
* ...one division less...
*/
for( i = dividend_size - 2; i >= 0; i--) {
n0 = dividend_ptr[i];
UDIV_QRNND_PREINV(dummy, r, r,
((n1 << normalization_steps)
| (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))),
divisor_limb, divisor_limb_inverted);
n1 = n0;
}
UDIV_QRNND_PREINV(dummy, r, r,
n1 << normalization_steps,
divisor_limb, divisor_limb_inverted);
return r >> normalization_steps;
}
else {
mpi_limb_t divisor_limb_inverted;
/* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The
* result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the
* most significant bit (with weight 2**N) implicit.
*
* Special case for DIVISOR_LIMB == 100...000.
*/
if( !(divisor_limb << 1) )
divisor_limb_inverted = ~(mpi_limb_t)0;
else
udiv_qrnnd(divisor_limb_inverted, dummy,
-divisor_limb, 0, divisor_limb);
i = dividend_size - 1;
r = dividend_ptr[i];
if( r >= divisor_limb )
r = 0;
else
i--;
for( ; i >= 0; i--) {
n0 = dividend_ptr[i];
UDIV_QRNND_PREINV(dummy, r, r,
n0, divisor_limb, divisor_limb_inverted);
}
return r;
}
}
else {
if( UDIV_NEEDS_NORMALIZATION ) {
int normalization_steps;
count_leading_zeros(normalization_steps, divisor_limb);
if( normalization_steps ) {
divisor_limb <<= normalization_steps;
n1 = dividend_ptr[dividend_size - 1];
r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps);
/* Possible optimization:
* if (r == 0
* && divisor_limb > ((n1 << normalization_steps)
* | (dividend_ptr[dividend_size - 2] >> ...)))
* ...one division less...
*/
for(i = dividend_size - 2; i >= 0; i--) {
n0 = dividend_ptr[i];
udiv_qrnnd (dummy, r, r,
((n1 << normalization_steps)
| (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))),
divisor_limb);
n1 = n0;
}
udiv_qrnnd (dummy, r, r,
n1 << normalization_steps,
divisor_limb);
return r >> normalization_steps;
}
}
/* No normalization needed, either because udiv_qrnnd doesn't require
* it, or because DIVISOR_LIMB is already normalized. */
i = dividend_size - 1;
r = dividend_ptr[i];
if(r >= divisor_limb)
r = 0;
else
i--;
for(; i >= 0; i--) {
n0 = dividend_ptr[i];
udiv_qrnnd (dummy, r, r, n0, divisor_limb);
}
return r;
}
}
/* Divide num (NP/NSIZE) by den (DP/DSIZE) and write
* the NSIZE-DSIZE least significant quotient limbs at QP
* and the DSIZE long remainder at NP. If QEXTRA_LIMBS is
* non-zero, generate that many fraction bits and append them after the
* other quotient limbs.
* Return the most significant limb of the quotient, this is always 0 or 1.
*
* Preconditions:
* 0. NSIZE >= DSIZE.
* 1. The most significant bit of the divisor must be set.
* 2. QP must either not overlap with the input operands at all, or
* QP + DSIZE >= NP must hold true. (This means that it's
* possible to put the quotient in the high part of NUM, right after the
* remainder in NUM.
* 3. NSIZE >= DSIZE, even if QEXTRA_LIMBS is non-zero.
*/
mpi_limb_t
mpihelp_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs,
mpi_ptr_t np, mpi_size_t nsize,
mpi_ptr_t dp, mpi_size_t dsize)
{
mpi_limb_t most_significant_q_limb = 0;
switch(dsize) {
case 0:
/* We are asked to divide by zero, so go ahead and do it! (To make
the compiler not remove this statement, return the value.) */
return 1 / dsize;
case 1:
{
mpi_size_t i;
mpi_limb_t n1;
mpi_limb_t d;
d = dp[0];
n1 = np[nsize - 1];
if( n1 >= d ) {
n1 -= d;
most_significant_q_limb = 1;
}
qp += qextra_limbs;
for( i = nsize - 2; i >= 0; i--)
udiv_qrnnd( qp[i], n1, n1, np[i], d );
qp -= qextra_limbs;
for( i = qextra_limbs - 1; i >= 0; i-- )
udiv_qrnnd (qp[i], n1, n1, 0, d);
np[0] = n1;
}
break;
case 2:
{
mpi_size_t i;
mpi_limb_t n1, n0, n2;
mpi_limb_t d1, d0;
np += nsize - 2;
d1 = dp[1];
d0 = dp[0];
n1 = np[1];
n0 = np[0];
if( n1 >= d1 && (n1 > d1 || n0 >= d0) ) {
sub_ddmmss (n1, n0, n1, n0, d1, d0);
most_significant_q_limb = 1;
}
for( i = qextra_limbs + nsize - 2 - 1; i >= 0; i-- ) {
mpi_limb_t q;
mpi_limb_t r;
if( i >= qextra_limbs )
np--;
else
np[0] = 0;
if( n1 == d1 ) {
/* Q should be either 111..111 or 111..110. Need special
* treatment of this rare case as normal division would
* give overflow. */
q = ~(mpi_limb_t)0;
r = n0 + d1;
if( r < d1 ) { /* Carry in the addition? */
add_ssaaaa( n1, n0, r - d0, np[0], 0, d0 );
qp[i] = q;
continue;
}
n1 = d0 - (d0 != 0?1:0);
n0 = -d0;
}
else {
udiv_qrnnd (q, r, n1, n0, d1);
umul_ppmm (n1, n0, d0, q);
}
n2 = np[0];
q_test:
if( n1 > r || (n1 == r && n0 > n2) ) {
/* The estimated Q was too large. */
q--;
sub_ddmmss (n1, n0, n1, n0, 0, d0);
r += d1;
if( r >= d1 ) /* If not carry, test Q again. */
goto q_test;
}
qp[i] = q;
sub_ddmmss (n1, n0, r, n2, n1, n0);
}
np[1] = n1;
np[0] = n0;
}
break;
default:
{
mpi_size_t i;
mpi_limb_t dX, d1, n0;
np += nsize - dsize;
dX = dp[dsize - 1];
d1 = dp[dsize - 2];
n0 = np[dsize - 1];
if( n0 >= dX ) {
if(n0 > dX || mpihelp_cmp(np, dp, dsize - 1) >= 0 ) {
mpihelp_sub_n(np, np, dp, dsize);
n0 = np[dsize - 1];
most_significant_q_limb = 1;
}
}
for( i = qextra_limbs + nsize - dsize - 1; i >= 0; i--) {
mpi_limb_t q;
mpi_limb_t n1, n2;
mpi_limb_t cy_limb;
if( i >= qextra_limbs ) {
np--;
n2 = np[dsize];
}
else {
n2 = np[dsize - 1];
MPN_COPY_DECR (np + 1, np, dsize);
np[0] = 0;
}
if( n0 == dX ) {
/* This might over-estimate q, but it's probably not worth
* the extra code here to find out. */
q = ~(mpi_limb_t)0;
}
else {
mpi_limb_t r;
udiv_qrnnd(q, r, n0, np[dsize - 1], dX);
umul_ppmm(n1, n0, d1, q);
while( n1 > r || (n1 == r && n0 > np[dsize - 2])) {
q--;
r += dX;
if( r < dX ) /* I.e. "carry in previous addition?" */
break;
n1 -= n0 < d1;
n0 -= d1;
}
}
/* Possible optimization: We already have (q * n0) and (1 * n1)
* after the calculation of q. Taking advantage of that, we
* could make this loop make two iterations less. */
cy_limb = mpihelp_submul_1(np, dp, dsize, q);
if( n2 != cy_limb ) {
mpihelp_add_n(np, np, dp, dsize);
q--;
}
qp[i] = q;
n0 = np[dsize - 1];
}
}
}
return most_significant_q_limb;
}
/****************
* Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB.
* Write DIVIDEND_SIZE limbs of quotient at QUOT_PTR.
* Return the single-limb remainder.
* There are no constraints on the value of the divisor.
*
* QUOT_PTR and DIVIDEND_PTR might point to the same limb.
*/
mpi_limb_t
mpihelp_divmod_1( mpi_ptr_t quot_ptr,
mpi_ptr_t dividend_ptr, mpi_size_t dividend_size,
mpi_limb_t divisor_limb)
{
mpi_size_t i;
mpi_limb_t n1, n0, r;
int dummy;
if( !dividend_size )
return 0;
/* If multiplication is much faster than division, and the
* dividend is large, pre-invert the divisor, and use
* only multiplications in the inner loop.
*
* This test should be read:
* Does it ever help to use udiv_qrnnd_preinv?
* && Does what we save compensate for the inversion overhead?
*/
if( UDIV_TIME > (2 * UMUL_TIME + 6)
&& (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME ) {
int normalization_steps;
count_leading_zeros( normalization_steps, divisor_limb );
if( normalization_steps ) {
mpi_limb_t divisor_limb_inverted;
divisor_limb <<= normalization_steps;
/* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The
* result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the
* most significant bit (with weight 2**N) implicit.
*/
/* Special case for DIVISOR_LIMB == 100...000. */
if( !(divisor_limb << 1) )
divisor_limb_inverted = ~(mpi_limb_t)0;
else
udiv_qrnnd(divisor_limb_inverted, dummy,
-divisor_limb, 0, divisor_limb);
n1 = dividend_ptr[dividend_size - 1];
r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps);
/* Possible optimization:
* if (r == 0
* && divisor_limb > ((n1 << normalization_steps)
* | (dividend_ptr[dividend_size - 2] >> ...)))
* ...one division less...
*/
for( i = dividend_size - 2; i >= 0; i--) {
n0 = dividend_ptr[i];
UDIV_QRNND_PREINV( quot_ptr[i + 1], r, r,
((n1 << normalization_steps)
| (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))),
divisor_limb, divisor_limb_inverted);
n1 = n0;
}
UDIV_QRNND_PREINV( quot_ptr[0], r, r,
n1 << normalization_steps,
divisor_limb, divisor_limb_inverted);
return r >> normalization_steps;
}
else {
mpi_limb_t divisor_limb_inverted;
/* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB. The
* result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the
* most significant bit (with weight 2**N) implicit.
*/
/* Special case for DIVISOR_LIMB == 100...000. */
if( !(divisor_limb << 1) )
divisor_limb_inverted = ~(mpi_limb_t) 0;
else
udiv_qrnnd(divisor_limb_inverted, dummy,
-divisor_limb, 0, divisor_limb);
i = dividend_size - 1;
r = dividend_ptr[i];
if( r >= divisor_limb )
r = 0;
else
quot_ptr[i--] = 0;
for( ; i >= 0; i-- ) {
n0 = dividend_ptr[i];
UDIV_QRNND_PREINV( quot_ptr[i], r, r,
n0, divisor_limb, divisor_limb_inverted);
}
return r;
}
}
else {
if(UDIV_NEEDS_NORMALIZATION) {
int normalization_steps;
count_leading_zeros (normalization_steps, divisor_limb);
if( normalization_steps ) {
divisor_limb <<= normalization_steps;
n1 = dividend_ptr[dividend_size - 1];
r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps);
/* Possible optimization:
* if (r == 0
* && divisor_limb > ((n1 << normalization_steps)
* | (dividend_ptr[dividend_size - 2] >> ...)))
* ...one division less...
*/
for( i = dividend_size - 2; i >= 0; i--) {
n0 = dividend_ptr[i];
udiv_qrnnd (quot_ptr[i + 1], r, r,
((n1 << normalization_steps)
| (n0 >> (BITS_PER_MPI_LIMB - normalization_steps))),
divisor_limb);
n1 = n0;
}
udiv_qrnnd (quot_ptr[0], r, r,
n1 << normalization_steps,
divisor_limb);
return r >> normalization_steps;
}
}
/* No normalization needed, either because udiv_qrnnd doesn't require
* it, or because DIVISOR_LIMB is already normalized. */
i = dividend_size - 1;
r = dividend_ptr[i];
if(r >= divisor_limb)
r = 0;
else
quot_ptr[i--] = 0;
for(; i >= 0; i--) {
n0 = dividend_ptr[i];
udiv_qrnnd( quot_ptr[i], r, r, n0, divisor_limb );
}
return r;
}
}
diff --git a/mpi/mpih-mul.c b/mpi/mpih-mul.c
index f402f4ae7..b457a0b5f 100644
--- a/mpi/mpih-mul.c
+++ b/mpi/mpih-mul.c
@@ -1,470 +1,470 @@
/* mpihelp-mul.c - MPI helper functions
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1994, 1996 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
* The GNU MP Library itself is published under the LGPL;
* however I decided to publish this code under the plain GPL.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include "mpi-internal.h"
#include "longlong.h"
#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \
do { \
if( (size) < KARATSUBA_THRESHOLD ) \
mul_n_basecase (prodp, up, vp, size); \
else \
mul_n (prodp, up, vp, size, tspace); \
} while (0);
#define MPN_SQR_N_RECURSE(prodp, up, size, tspace) \
do { \
if ((size) < KARATSUBA_THRESHOLD) \
mpih_sqr_n_basecase (prodp, up, size); \
else \
mpih_sqr_n (prodp, up, size, tspace); \
} while (0);
/* Multiply the natural numbers u (pointed to by UP) and v (pointed to by VP),
* both with SIZE limbs, and store the result at PRODP. 2 * SIZE limbs are
* always stored. Return the most significant limb.
*
* Argument constraints:
* 1. PRODP != UP and PRODP != VP, i.e. the destination
* must be distinct from the multiplier and the multiplicand.
*
*
* Handle simple cases with traditional multiplication.
*
* This is the most critical code of multiplication. All multiplies rely
* on this, both small and huge. Small ones arrive here immediately. Huge
* ones arrive here as this is the base case for Karatsuba's recursive
* algorithm below.
*/
static mpi_limb_t
mul_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up,
mpi_ptr_t vp, mpi_size_t size)
{
mpi_size_t i;
mpi_limb_t cy;
mpi_limb_t v_limb;
/* Multiply by the first limb in V separately, as the result can be
* stored (not added) to PROD. We also avoid a loop for zeroing. */
v_limb = vp[0];
if( v_limb <= 1 ) {
if( v_limb == 1 )
MPN_COPY( prodp, up, size );
else
MPN_ZERO( prodp, size );
cy = 0;
}
else
cy = mpihelp_mul_1( prodp, up, size, v_limb );
prodp[size] = cy;
prodp++;
/* For each iteration in the outer loop, multiply one limb from
* U with one limb from V, and add it to PROD. */
for( i = 1; i < size; i++ ) {
v_limb = vp[i];
if( v_limb <= 1 ) {
cy = 0;
if( v_limb == 1 )
cy = mpihelp_add_n(prodp, prodp, up, size);
}
else
cy = mpihelp_addmul_1(prodp, up, size, v_limb);
prodp[size] = cy;
prodp++;
}
return cy;
}
static void
mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp,
mpi_size_t size, mpi_ptr_t tspace )
{
if( size & 1 ) {
/* The size is odd, and the code below doesn't handle that.
* Multiply the least significant (size - 1) limbs with a recursive
* call, and handle the most significant limb of S1 and S2
* separately.
* A slightly faster way to do this would be to make the Karatsuba
* code below behave as if the size were even, and let it check for
* odd size in the end. I.e., in essence move this code to the end.
* Doing so would save us a recursive call, and potentially make the
* stack grow a lot less.
*/
mpi_size_t esize = size - 1; /* even size */
mpi_limb_t cy_limb;
MPN_MUL_N_RECURSE( prodp, up, vp, esize, tspace );
cy_limb = mpihelp_addmul_1( prodp + esize, up, esize, vp[esize] );
prodp[esize + esize] = cy_limb;
cy_limb = mpihelp_addmul_1( prodp + esize, vp, size, up[esize] );
prodp[esize + size] = cy_limb;
}
else {
/* Anatolij Alekseevich Karatsuba's divide-and-conquer algorithm.
*
* Split U in two pieces, U1 and U0, such that
* U = U0 + U1*(B**n),
* and V in V1 and V0, such that
* V = V0 + V1*(B**n).
*
* UV is then computed recursively using the identity
*
* 2n n n n
* UV = (B + B )U V + B (U -U )(V -V ) + (B + 1)U V
* 1 1 1 0 0 1 0 0
*
* Where B = 2**BITS_PER_MP_LIMB.
*/
mpi_size_t hsize = size >> 1;
mpi_limb_t cy;
int negflg;
/* Product H. ________________ ________________
* |_____U1 x V1____||____U0 x V0_____|
* Put result in upper part of PROD and pass low part of TSPACE
* as new TSPACE.
*/
MPN_MUL_N_RECURSE(prodp + size, up + hsize, vp + hsize, hsize, tspace);
/* Product M. ________________
* |_(U1-U0)(V0-V1)_|
*/
if( mpihelp_cmp(up + hsize, up, hsize) >= 0 ) {
mpihelp_sub_n(prodp, up + hsize, up, hsize);
negflg = 0;
}
else {
mpihelp_sub_n(prodp, up, up + hsize, hsize);
negflg = 1;
}
if( mpihelp_cmp(vp + hsize, vp, hsize) >= 0 ) {
mpihelp_sub_n(prodp + hsize, vp + hsize, vp, hsize);
negflg ^= 1;
}
else {
mpihelp_sub_n(prodp + hsize, vp, vp + hsize, hsize);
/* No change of NEGFLG. */
}
/* Read temporary operands from low part of PROD.
* Put result in low part of TSPACE using upper part of TSPACE
* as new TSPACE.
*/
MPN_MUL_N_RECURSE(tspace, prodp, prodp + hsize, hsize, tspace + size);
/* Add/copy product H. */
MPN_COPY (prodp + hsize, prodp + size, hsize);
cy = mpihelp_add_n( prodp + size, prodp + size,
prodp + size + hsize, hsize);
/* Add product M (if NEGFLG M is a negative number) */
if(negflg)
cy -= mpihelp_sub_n(prodp + hsize, prodp + hsize, tspace, size);
else
cy += mpihelp_add_n(prodp + hsize, prodp + hsize, tspace, size);
/* Product L. ________________ ________________
* |________________||____U0 x V0_____|
* Read temporary operands from low part of PROD.
* Put result in low part of TSPACE using upper part of TSPACE
* as new TSPACE.
*/
MPN_MUL_N_RECURSE(tspace, up, vp, hsize, tspace + size);
/* Add/copy Product L (twice) */
cy += mpihelp_add_n(prodp + hsize, prodp + hsize, tspace, size);
if( cy )
mpihelp_add_1(prodp + hsize + size, prodp + hsize + size, hsize, cy);
MPN_COPY(prodp, tspace, hsize);
cy = mpihelp_add_n(prodp + hsize, prodp + hsize, tspace + hsize, hsize);
if( cy )
mpihelp_add_1(prodp + size, prodp + size, size, 1);
}
}
void
mpih_sqr_n_basecase( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size )
{
mpi_size_t i;
mpi_limb_t cy_limb;
mpi_limb_t v_limb;
/* Multiply by the first limb in V separately, as the result can be
* stored (not added) to PROD. We also avoid a loop for zeroing. */
v_limb = up[0];
if( v_limb <= 1 ) {
if( v_limb == 1 )
MPN_COPY( prodp, up, size );
else
MPN_ZERO(prodp, size);
cy_limb = 0;
}
else
cy_limb = mpihelp_mul_1( prodp, up, size, v_limb );
prodp[size] = cy_limb;
prodp++;
/* For each iteration in the outer loop, multiply one limb from
* U with one limb from V, and add it to PROD. */
for( i=1; i < size; i++) {
v_limb = up[i];
if( v_limb <= 1 ) {
cy_limb = 0;
if( v_limb == 1 )
cy_limb = mpihelp_add_n(prodp, prodp, up, size);
}
else
cy_limb = mpihelp_addmul_1(prodp, up, size, v_limb);
prodp[size] = cy_limb;
prodp++;
}
}
void
mpih_sqr_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size, mpi_ptr_t tspace)
{
if( size & 1 ) {
/* The size is odd, and the code below doesn't handle that.
* Multiply the least significant (size - 1) limbs with a recursive
* call, and handle the most significant limb of S1 and S2
* separately.
* A slightly faster way to do this would be to make the Karatsuba
* code below behave as if the size were even, and let it check for
* odd size in the end. I.e., in essence move this code to the end.
* Doing so would save us a recursive call, and potentially make the
* stack grow a lot less.
*/
mpi_size_t esize = size - 1; /* even size */
mpi_limb_t cy_limb;
MPN_SQR_N_RECURSE( prodp, up, esize, tspace );
cy_limb = mpihelp_addmul_1( prodp + esize, up, esize, up[esize] );
prodp[esize + esize] = cy_limb;
cy_limb = mpihelp_addmul_1( prodp + esize, up, size, up[esize] );
prodp[esize + size] = cy_limb;
}
else {
mpi_size_t hsize = size >> 1;
mpi_limb_t cy;
/* Product H. ________________ ________________
* |_____U1 x U1____||____U0 x U0_____|
* Put result in upper part of PROD and pass low part of TSPACE
* as new TSPACE.
*/
MPN_SQR_N_RECURSE(prodp + size, up + hsize, hsize, tspace);
/* Product M. ________________
* |_(U1-U0)(U0-U1)_|
*/
if( mpihelp_cmp( up + hsize, up, hsize) >= 0 )
mpihelp_sub_n( prodp, up + hsize, up, hsize);
else
mpihelp_sub_n (prodp, up, up + hsize, hsize);
/* Read temporary operands from low part of PROD.
* Put result in low part of TSPACE using upper part of TSPACE
* as new TSPACE. */
MPN_SQR_N_RECURSE(tspace, prodp, hsize, tspace + size);
/* Add/copy product H */
MPN_COPY(prodp + hsize, prodp + size, hsize);
cy = mpihelp_add_n(prodp + size, prodp + size,
prodp + size + hsize, hsize);
/* Add product M (if NEGFLG M is a negative number). */
cy -= mpihelp_sub_n (prodp + hsize, prodp + hsize, tspace, size);
/* Product L. ________________ ________________
* |________________||____U0 x U0_____|
* Read temporary operands from low part of PROD.
* Put result in low part of TSPACE using upper part of TSPACE
* as new TSPACE. */
MPN_SQR_N_RECURSE (tspace, up, hsize, tspace + size);
/* Add/copy Product L (twice). */
cy += mpihelp_add_n (prodp + hsize, prodp + hsize, tspace, size);
if( cy )
mpihelp_add_1(prodp + hsize + size, prodp + hsize + size,
hsize, cy);
MPN_COPY(prodp, tspace, hsize);
cy = mpihelp_add_n (prodp + hsize, prodp + hsize, tspace + hsize, hsize);
if( cy )
mpihelp_add_1 (prodp + size, prodp + size, size, 1);
}
}
/* This should be made into an inline function in gmp.h. */
void
mpihelp_mul_n( mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size)
{
/* FIXME: mpi_alloc_limb_space, secure arg is wrong! */
if( up == vp ) {
if( size < KARATSUBA_THRESHOLD )
mpih_sqr_n_basecase( prodp, up, size );
else {
mpi_ptr_t tspace;
tspace = mpi_alloc_limb_space( 2 * size, 0 );
mpih_sqr_n( prodp, up, size, tspace );
mpi_free_limb_space( tspace );
}
}
else {
if( size < KARATSUBA_THRESHOLD )
mul_n_basecase( prodp, up, vp, size );
else {
mpi_ptr_t tspace;
tspace = mpi_alloc_limb_space( 2 * size, 0 );
mul_n (prodp, up, vp, size, tspace);
mpi_free_limb_space( tspace );
}
}
}
/* Multiply the natural numbers u (pointed to by UP, with USIZE limbs)
* and v (pointed to by VP, with VSIZE limbs), and store the result at
* PRODP. USIZE + VSIZE limbs are always stored, but if the input
* operands are normalized. Return the most significant limb of the
* result.
*
* NOTE: The space pointed to by PRODP is overwritten before finished
* with U and V, so overlap is an error.
*
* Argument constraints:
* 1. USIZE >= VSIZE.
* 2. PRODP != UP and PRODP != VP, i.e. the destination
* must be distinct from the multiplier and the multiplicand.
*/
mpi_limb_t
mpihelp_mul( mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t usize,
mpi_ptr_t vp, mpi_size_t vsize)
{
mpi_ptr_t prod_endp = prodp + usize + vsize - 1;
mpi_limb_t cy;
mpi_ptr_t tspace;
if( vsize < KARATSUBA_THRESHOLD ) {
mpi_size_t i;
mpi_limb_t v_limb;
if( !vsize )
return 0;
/* Multiply by the first limb in V separately, as the result can be
* stored (not added) to PROD. We also avoid a loop for zeroing. */
v_limb = vp[0];
if( v_limb <= 1 ) {
if( v_limb == 1 )
MPN_COPY( prodp, up, usize );
else
MPN_ZERO( prodp, usize );
cy = 0;
}
else
cy = mpihelp_mul_1( prodp, up, usize, v_limb );
prodp[usize] = cy;
prodp++;
/* For each iteration in the outer loop, multiply one limb from
* U with one limb from V, and add it to PROD. */
for( i = 1; i < vsize; i++ ) {
v_limb = vp[i];
if( v_limb <= 1 ) {
cy = 0;
if( v_limb == 1 )
cy = mpihelp_add_n(prodp, prodp, up, usize);
}
else
cy = mpihelp_addmul_1(prodp, up, usize, v_limb);
prodp[usize] = cy;
prodp++;
}
return cy;
}
/* FIXME: mpi_alloc_limb_space, secure arg is wrong! */
tspace = mpi_alloc_limb_space( 2 * vsize, 0 );
MPN_MUL_N_RECURSE( prodp, up, vp, vsize, tspace );
prodp += vsize;
up += vsize;
usize -= vsize;
if( usize >= vsize ) {
/* FIXME: mpi_alloc_limb_space, secure arg is wrong! */
mpi_ptr_t tp = mpi_alloc_limb_space( 2 * vsize, 0 );
do {
MPN_MUL_N_RECURSE( tp, up, vp, vsize, tspace );
cy = mpihelp_add_n( prodp, prodp, tp, vsize );
mpihelp_add_1( prodp + vsize, tp + vsize, vsize, cy );
prodp += vsize;
up += vsize;
usize -= vsize;
} while( usize >= vsize );
mpi_free_limb_space( tp );
}
if( usize ) {
mpihelp_mul( tspace, vp, vsize, up, usize );
cy = mpihelp_add_n( prodp, prodp, tspace, vsize);
mpihelp_add_1( prodp + vsize, tspace + vsize, usize, cy );
}
mpi_free_limb_space( tspace );
return *prod_endp;
}
diff --git a/mpi/mpih-sub.c b/mpi/mpih-sub.c
index 52d25b329..7bfcddeae 100644
--- a/mpi/mpih-sub.c
+++ b/mpi/mpih-sub.c
@@ -1,81 +1,81 @@
/* mpihelp-sub.c - MPI helper functions
* Copyright (C) 1998 Free Software Foundation, Inc.
* Copyright (C) 1994, 1996 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
* The GNU MP Library itself is published under the LGPL;
* however I decided to publish this code under the plain GPL.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include "mpi-internal.h"
#ifndef __GNUC__
mpi_limb_t
mpihelp_sub_1(mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr,
mpi_size_t s1_size, mpi_limb_t s2_limb )
{
mpi_limb_t x;
x = *s1_ptr++;
s2_limb = x - s2_limb;
*res_ptr++ = s2_limb;
if( s2_limb > x ) {
while( --s1_size ) {
x = *s1_ptr++;
*res_ptr++ = x - 1;
if( x )
goto leave;
}
return 1;
}
leave:
if( res_ptr != s1_ptr ) {
mpi_size_t i;
for( i=0; i < s1_size-1; i++ )
res_ptr[i] = s1_ptr[i];
}
return 0;
}
mpi_limb_t
mpihelp_sub( mpi_ptr_t res_ptr, mpi_ptr_t s1_ptr, mpi_size_t s1_size,
mpi_ptr_t s2_ptr, mpi_size_t s2_size)
{
mpi_limb_t cy = 0;
if( s2_size )
cy = mpihelp_sub_n(res_ptr, s1_ptr, s2_ptr, s2_size);
if( s1_size - s2_size )
cy = mpihelp_sub_1(res_ptr + s2_size, s1_ptr + s2_size,
s1_size - s2_size, cy);
return cy;
}
#endif
diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c
index 18af9e04b..d90cd4d34 100644
--- a/mpi/mpiutil.c
+++ b/mpi/mpiutil.c
@@ -1,374 +1,374 @@
/* mpiutil.ac - Utility functions for MPI
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 "mpi.h"
#include "mpi-internal.h"
#include "memory.h"
#include "util.h"
#ifdef M_DEBUG
#undef mpi_alloc
#undef mpi_alloc_secure
#undef mpi_free
#endif
/****************
* fixme: It was a bad idea to use the number of limbs to allocate
* because on a alpha the limbs are large but we normally need
* integers of n bits - So we should chnage this to bits (or bytes).
*
* But mpi_alloc is used in a lot of places :-)
*/
MPI
#ifdef M_DEBUG
mpi_debug_alloc( unsigned nlimbs, const char *info )
#else
mpi_alloc( unsigned nlimbs )
#endif
{
MPI a;
if( DBG_MEMORY )
log_debug("mpi_alloc(%u)\n", nlimbs*BITS_PER_MPI_LIMB );
#ifdef M_DEBUG
a = m_debug_alloc( sizeof *a, info );
a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 0, info ) : NULL;
#else
a = m_alloc( sizeof *a );
a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL;
#endif
a->alloced = nlimbs;
a->nlimbs = 0;
a->sign = 0;
a->flags = 0;
a->nbits = 0;
return a;
}
void
mpi_m_check( MPI a )
{
m_check(a);
m_check(a->d);
}
MPI
#ifdef M_DEBUG
mpi_debug_alloc_secure( unsigned nlimbs, const char *info )
#else
mpi_alloc_secure( unsigned nlimbs )
#endif
{
MPI a;
if( DBG_MEMORY )
log_debug("mpi_alloc_secure(%u)\n", nlimbs*BITS_PER_MPI_LIMB );
#ifdef M_DEBUG
a = m_debug_alloc( sizeof *a, info );
a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 1, info ) : NULL;
#else
a = m_alloc( sizeof *a );
a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL;
#endif
a->alloced = nlimbs;
a->flags = 1;
a->nlimbs = 0;
a->sign = 0;
a->nbits = 0;
return a;
}
mpi_ptr_t
#ifdef M_DEBUG
mpi_debug_alloc_limb_space( unsigned nlimbs, int secure, const char *info )
#else
mpi_alloc_limb_space( unsigned nlimbs, int secure )
#endif
{
size_t len = nlimbs * sizeof(mpi_limb_t);
if( DBG_MEMORY )
log_debug("mpi_alloc_limb_space(%u)\n", (unsigned)len*8 );
#ifdef M_DEBUG
return secure? m_debug_alloc_secure(len, info):m_debug_alloc( len, info );
#else
return secure? m_alloc_secure( len ):m_alloc( len );
#endif
}
void
#ifdef M_DEBUG
mpi_debug_free_limb_space( mpi_ptr_t a, const char *info )
#else
mpi_free_limb_space( mpi_ptr_t a )
#endif
{
if( !a )
return;
if( DBG_MEMORY )
log_debug("mpi_free_limb_space of size %lu\n", (ulong)m_size(a)*8 );
m_free(a);
}
void
mpi_assign_limb_space( MPI a, mpi_ptr_t ap, unsigned nlimbs )
{
mpi_free_limb_space(a->d);
a->d = ap;
a->alloced = nlimbs;
}
/****************
* Resize the array of A to NLIMBS. the additional space is cleared
* (set to 0) [done by m_realloc()]
*/
void
#ifdef M_DEBUG
mpi_debug_resize( MPI a, unsigned nlimbs, const char *info )
#else
mpi_resize( MPI a, unsigned nlimbs )
#endif
{
if( nlimbs <= a->alloced )
return; /* no need to do it */
/* FIXME: add realloc_secure based on a->secure */
#ifdef M_DEBUG
if( a->d )
a->d = m_debug_realloc(a->d, nlimbs * sizeof(mpi_limb_t), info );
else
a->d = m_debug_alloc_clear( nlimbs * sizeof(mpi_limb_t), info );
#else
if( a->d )
a->d = m_realloc(a->d, nlimbs * sizeof(mpi_limb_t) );
else
a->d = m_alloc_clear( nlimbs * sizeof(mpi_limb_t) );
#endif
a->alloced = nlimbs;
}
void
mpi_clear( MPI a )
{
a->nlimbs = 0;
a->nbits = 0;
a->flags = 0;
}
void
#ifdef M_DEBUG
mpi_debug_free( MPI a, const char *info )
#else
mpi_free( MPI a )
#endif
{
if( !a )
return;
if( DBG_MEMORY )
log_debug("mpi_free\n" );
if( a->flags & 4 )
m_free( a->d );
else {
#ifdef M_DEBUG
mpi_debug_free_limb_space(a->d, info);
#else
mpi_free_limb_space(a->d);
#endif
}
if( a->flags & ~7 )
log_bug("invalid flag value in mpi\n");
m_free(a);
}
void
mpi_set_secure( MPI a )
{
mpi_ptr_t ap, bp;
if( (a->flags & 1) )
return;
a->flags |= 1;
ap = a->d;
if( !a->nlimbs ) {
assert(!ap);
return;
}
#ifdef M_DEBUG
bp = mpi_debug_alloc_limb_space( a->nlimbs, 1, "set_secure" );
#else
bp = mpi_alloc_limb_space( a->nlimbs, 1 );
#endif
MPN_COPY( bp, ap, a->nlimbs );
a->d = bp;
#ifdef M_DEBUG
mpi_debug_free_limb_space(ap, "set_secure");
#else
mpi_free_limb_space(ap);
#endif
}
MPI
mpi_set_opaque( MPI a, void *p, int len )
{
if( !a ) {
#ifdef M_DEBUG
a = mpi_debug_alloc(0,"alloc_opaque");
#else
a = mpi_alloc(0);
#endif
}
if( a->flags & 4 )
m_free( a->d );
else {
#ifdef M_DEBUG
mpi_debug_free_limb_space(a->d, "alloc_opaque");
#else
mpi_free_limb_space(a->d);
#endif
}
a->d = p;
a->alloced = 0;
a->nlimbs = 0;
a->nbits = len;
a->flags = 4;
return a;
}
void *
mpi_get_opaque( MPI a, int *len )
{
if( !(a->flags & 4) )
log_bug("mpi_get_opaque on normal mpi\n");
if( len )
*len = a->nbits;
return a->d;
}
/****************
* Note: This copy function should not interpret the MPI
* but copy it transparently.
*/
MPI
#ifdef M_DEBUG
mpi_debug_copy( MPI a, const char *info )
#else
mpi_copy( MPI a )
#endif
{
int i;
MPI b;
if( a && (a->flags & 4) ) {
void *p = m_is_secure(a->d)? m_alloc_secure( a->nbits )
: m_alloc( a->nbits );
memcpy( p, a->d, a->nbits );
b = mpi_set_opaque( NULL, p, a->nbits );
}
else if( a ) {
#ifdef M_DEBUG
b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info )
: mpi_debug_alloc( a->nlimbs, info );
#else
b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
: mpi_alloc( a->nlimbs );
#endif
b->nlimbs = a->nlimbs;
b->sign = a->sign;
b->flags = a->flags;
b->nbits = a->nbits;
for(i=0; i < b->nlimbs; i++ )
b->d[i] = a->d[i];
}
else
b = NULL;
return b;
}
void
mpi_set( MPI w, MPI u)
{
mpi_ptr_t wp, up;
mpi_size_t usize = u->nlimbs;
int usign = u->sign;
RESIZE_IF_NEEDED(w, usize);
wp = w->d;
up = u->d;
MPN_COPY( wp, up, usize );
w->nlimbs = usize;
w->nbits = u->nbits;
w->flags = u->flags;
w->sign = usign;
}
void
mpi_set_ui( MPI w, unsigned long u)
{
RESIZE_IF_NEEDED(w, 1);
w->d[0] = u;
w->nlimbs = u? 1:0;
w->sign = 0;
w->nbits = 0;
w->flags = 0;
}
MPI
mpi_alloc_set_ui( unsigned long u)
{
#ifdef M_DEBUG
MPI w = mpi_debug_alloc(1,"alloc_set_ui");
#else
MPI w = mpi_alloc(1);
#endif
w->d[0] = u;
w->nlimbs = u? 1:0;
w->sign = 0;
return w;
}
void
mpi_swap( MPI a, MPI b)
{
struct gcry_mpi tmp;
tmp = *a; *a = *b; *b = tmp;
}
diff --git a/po/de.po b/po/de.po
index a3b700a80..b8cad6d90 100644
--- a/po/de.po
+++ b/po/de.po
@@ -1,3245 +1,3340 @@
# GnuPG german translation
# Copyright (C) 1998 Free Software Foundation, Inc.
# Walter Koch <walterk@dip.de>, 1998.
#
msgid ""
msgstr ""
-"POT-Creation-Date: 1998-12-09 00:39+0100\n"
+"POT-Creation-Date: 1998-12-17 18:30+0100\n"
"PO-Revision-Date: 1998-12-13 22:34+0100\n"
"Last-Translator: Walter Koch <walterk@mail.dip.de>\n"
"Language-Team: German <de@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=\n"
"Date: 1998-01-26 22:08:36+0100\n"
"From: Werner Koch <wk@frodo>\n"
"Xgettext-Options: --default-domain=gnupg --directory=.. --add-comments "
"--keyword=_ --keyword=N_ --files-from=./POTFILES.in\n"
"Files: util/secmem.c util/argparse.c cipher/random.c cipher/rand-dummy.c "
"cipher/rand-unix.c cipher/rand-w32.c g10/g10.c g10/pkclist.c g10/keygen.c "
"g10/decrypt.c g10/encode.c g10/import.c g10/keyedit.c g10/keylist.c "
"g10/mainproc.c g10/passphrase.c g10/plaintext.c g10/pref.c g10/seckey-cert.c "
"g10/sig-check.c g10/sign.c g10/trustdb.c g10/verify.c\n"
#: util/secmem.c:77
msgid "Warning: using insecure memory!\n"
msgstr ""
"Warnung: Sensible Daten könnten auf Platte ausgelagert werden.\n"
" Um dies zu vermeiden, kann das Programm suid(root) installiert werden.\n"
" Bitte wenden Sie sich hierzu an den Systemadministrator.\n"
#: util/miscutil.c:143
msgid "yes"
msgstr "ja"
#: util/miscutil.c:144
msgid "yY"
msgstr "jJ"
#: util/errors.c:54
msgid "General error"
msgstr "Allgemeiner Fehler"
#: util/errors.c:55
msgid "Unknown packet type"
msgstr "Unbekannter Pakettyp"
#: util/errors.c:56
msgid "Unknown version"
msgstr "Unbekannte Version"
#: util/errors.c:57
msgid "Unknown pubkey algorithm"
msgstr "Unbekanntes Public-Key Verfahren"
#: util/errors.c:58
msgid "Unknown digest algorithm"
msgstr "Unbekanntes Hashverfahren"
#: util/errors.c:59
msgid "Bad public key"
msgstr "Falscher öffentlicher Schüssel"
#: util/errors.c:60
msgid "Bad secret key"
msgstr "Falscher geheimer Schlüssel"
#: util/errors.c:61
msgid "Bad signature"
msgstr "Falsche Unterschrift"
#: util/errors.c:62
msgid "Checksum error"
msgstr "Prüfsummen-Fehler"
#: util/errors.c:63
msgid "Bad passphrase"
msgstr "Falsches Mantra"
#: util/errors.c:64
msgid "Public key not found"
msgstr "Öffentlicher Schlüssel nicht gefunden"
#: util/errors.c:65
msgid "Unknown cipher algorithm"
msgstr "Unbekanntes Verschlüsselungsverfahren"
#: util/errors.c:66
msgid "Can't open the keyring"
msgstr "Der Schlüsselbund kann nicht geöffnet werden"
#: util/errors.c:67
msgid "Invalid packet"
msgstr "Ungültiges Paket"
#: util/errors.c:68
msgid "Invalid armor"
msgstr "Ungültige ASCII-Hülle"
#: util/errors.c:69
msgid "No such user id"
msgstr "Keine User-ID"
#: util/errors.c:70
msgid "Secret key not available"
msgstr "Geheimer Schlüssel ist nicht vorhanden"
#: util/errors.c:71
msgid "Wrong secret key used"
msgstr "Falscher geheimer Schlüssel benutzt"
#: util/errors.c:72
msgid "Not supported"
msgstr "Wird nicht unterstützt"
#: util/errors.c:73
msgid "Bad key"
msgstr "Falscher Schlüssel"
#: util/errors.c:74
msgid "File read error"
msgstr "Dateilesefehler"
#: util/errors.c:75
msgid "File write error"
msgstr "Dateischreibfehler"
#: util/errors.c:76
msgid "Unknown compress algorithm"
msgstr "Unbekanntes Komprimierverfahren"
#: util/errors.c:77
msgid "File open error"
msgstr "Fehler beim Öffnen der Datei"
#: util/errors.c:78
msgid "File create error"
msgstr "Fehler beim Erzeugen der Datei"
#: util/errors.c:79
msgid "Invalid passphrase"
msgstr "Ungültiges Mantra"
#: util/errors.c:80
msgid "Unimplemented pubkey algorithm"
msgstr "Öffentliches Schlüsselverfahren ist nicht implementiert."
#: util/errors.c:81
msgid "Unimplemented cipher algorithm"
msgstr "Verschlüsselungsverfahren ist nicht implementiert"
#: util/errors.c:82
msgid "Unknown signature class"
msgstr "Unbekannte Unterschriftenklasse"
#: util/errors.c:83
msgid "Trust database error"
msgstr "Fehler in der Trust-DB"
#: util/errors.c:84
msgid "Bad MPI"
msgstr "Falsche MPI"
#: util/errors.c:85
msgid "Resource limit"
msgstr "Zu wenig Resourcen"
#: util/errors.c:86
msgid "Invalid keyring"
msgstr "Ungültiger Schlüsselbund"
#: util/errors.c:87
msgid "Bad certificate"
msgstr "Falsches Zertifikat"
#: util/errors.c:88
msgid "Malformed user id"
msgstr "Ungünstig aufgebaute User-ID"
#: util/errors.c:89
msgid "File close error"
msgstr "Fehler beim Schließen der Datei"
#: util/errors.c:90
msgid "File rename error"
msgstr "Fehler beim Umbenennen einer Datei"
#: util/errors.c:91
msgid "File delete error"
msgstr "Fehler beim Löschen einer Datei"
#: util/errors.c:92
msgid "Unexpected data"
msgstr "Unerwartete Daten"
#: util/errors.c:93
msgid "Timestamp conflict"
msgstr "Zeitangaben differieren"
#: util/errors.c:94
msgid "Unusable pubkey algorithm"
msgstr "Unbenutzbares öffentliches Schlüsselverfahren"
#: util/errors.c:95
msgid "File exists"
msgstr "Datei existiert bereits"
#: util/errors.c:96
msgid "Weak key"
msgstr "Unsicherer Schlüssel"
#: util/logger.c:178
#, c-format
msgid "... this is a bug (%s:%d:%s)\n"
msgstr "Ohhh jeeee ... dies ist eine Wanze (Programmfehler) (%s:%d:%s)\n"
#: util/logger.c:184
#, c-format
msgid "you found a bug ... (%s:%d)\n"
msgstr "Sie haben eine Wanze (Programmfehler) gefunden ... (%s:%d)\n"
-#: cipher/random.c:379
+#: cipher/random.c:406
msgid "WARNING: using insecure random number generator!!\n"
-msgstr "WARNUNG: Der Zufallszahlengenerator erzeugt keine echten Zufallszahlen!\n"
+msgstr ""
+"WARNUNG: Der Zufallszahlengenerator erzeugt keine echten Zufallszahlen!\n"
-#: cipher/random.c:380
+#: cipher/random.c:407
msgid ""
"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"
msgstr ""
"Der Zufallszahlengenerator (RNG) ist lediglich ein \"kludge\", um das\n"
"Übersetzen des Programms zu ermöglichen - es ist KEIN starker RNG!\n"
"\n"
"BENUTZEN SIE DIE DURCH DIESES PROGRAMM ERZEUGTEN DATEN NICHT!\n"
"\n"
-#: cipher/rndlinux.c:154
+#: cipher/rndlinux.c:118
#, c-format
msgid ""
"\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"
msgstr ""
"\n"
"Es sind nicht genügend Zufallswerte vorhanden. Bitte führen Sie andere\n"
"Arbeiten durch, damit das Betriebssystem weitere Entropie sammeln kann!\n"
"(Es werden noch %d Byte benötigt.)\n"
-#: g10/g10.c:158
+#: g10/g10.c:160
msgid ""
"@Commands:\n"
" "
msgstr ""
"@Kommandos:\n"
" "
-#: g10/g10.c:161
+#: g10/g10.c:163
msgid "|[file]|make a signature"
msgstr "|[file]|Eine Unterschrift erzeugen"
-#: g10/g10.c:162
+#: g10/g10.c:164
msgid "|[file]|make a clear text signature"
msgstr "|[file]|Eine Klartextunterschrift erzeugen"
-#: g10/g10.c:163
+#: g10/g10.c:165
msgid "make a detached signature"
msgstr "Eine abgetrennte Unterschrift erzeugen"
-#: g10/g10.c:164
+#: g10/g10.c:166
msgid "encrypt data"
msgstr "Daten verschlüsseln"
-#: g10/g10.c:165
+#: g10/g10.c:167
msgid "encryption only with symmetric cipher"
msgstr "Daten nur symmetrisch verschlüsseln"
-#: g10/g10.c:166
+#: g10/g10.c:168
msgid "store only"
msgstr "Nur speichern"
-#: g10/g10.c:167
+#: g10/g10.c:169
msgid "decrypt data (default)"
msgstr "Daten entschlüsseln (Voreinstellung)"
-#: g10/g10.c:168
+#: g10/g10.c:170
msgid "verify a signature"
msgstr "Signatur prüfen"
-#: g10/g10.c:170
+#: g10/g10.c:172
msgid "list keys"
msgstr "Liste der Schlüssel"
-#: g10/g10.c:171
+#: g10/g10.c:173
msgid "list keys and signatures"
msgstr "Liste der Schlüssel und ihrer Signaturen"
-#: g10/g10.c:172
+#: g10/g10.c:174
msgid "check key signatures"
msgstr "Signaturen der Schlüssel prüfen"
-#: g10/g10.c:173
+#: g10/g10.c:175
msgid "list keys and fingerprints"
msgstr "Liste der Schlüssel und ihrer \"Fingerabdrücke\""
-#: g10/g10.c:174
+#: g10/g10.c:176
msgid "list secret keys"
msgstr "Liste der geheimen Schlüssel"
-#: g10/g10.c:176
+#: g10/g10.c:178
msgid "generate a new key pair"
msgstr "Ein neues Schlüsselpaar erzeugen"
-#: g10/g10.c:178
+#: g10/g10.c:180
msgid "remove key from the public keyring"
msgstr "Schlüssel entfernen"
-#: g10/g10.c:180
+#: g10/g10.c:182
msgid "sign or edit a key"
msgstr "Unterschreiben oder Bearbeiten eines Schlüssels"
-#: g10/g10.c:181
+#: g10/g10.c:183
msgid "generate a revocation certificate"
msgstr "Ein Schlüsselwiderruf-Zertifikat erzeugen"
-#: g10/g10.c:183
+#: g10/g10.c:185
msgid "export keys"
msgstr "Schlüssel exportieren"
-#: g10/g10.c:185
+#: g10/g10.c:188
msgid "import/merge keys"
msgstr "Schlüssel importieren/kombinieren"
-#: g10/g10.c:187
+#: g10/g10.c:190
msgid "list only the sequence of packets"
msgstr "Lediglich die Struktur der Datenpackete anzeigen"
-#: g10/g10.c:190
+#: g10/g10.c:193
msgid "export the ownertrust values"
msgstr "Exportieren der \"Owner trust\" Werte"
-#: g10/g10.c:192
+#: g10/g10.c:195
msgid "import ownertrust values"
msgstr "Importieren der \"Owner trust\" Werte"
-#: g10/g10.c:194
+#: g10/g10.c:197
msgid "|[NAMES]|update the trust database"
msgstr "|[NAMES]|Ändern der \"Trust\"-Datenbank"
-#: g10/g10.c:196
+#: g10/g10.c:199
msgid "|[NAMES]|check the trust database"
msgstr "|[NAMES]|Überprüfen der \"Trust\"-Datenbank"
-#: g10/g10.c:197
+#: g10/g10.c:200
msgid "fix a corrupted trust database"
msgstr "Reparieren einer beschädigten \"Trust\"-Datenbank"
-#: g10/g10.c:198
+#: g10/g10.c:201
msgid "De-Armor a file or stdin"
msgstr "Datei oder stdin von der ASCII-Hülle befreien"
-#: g10/g10.c:199
+#: g10/g10.c:202
msgid "En-Armor a file or stdin"
msgstr "Datei oder stdin in eine ASCII-Hülle einpacken"
-#: g10/g10.c:200
+#: g10/g10.c:203
msgid "|algo [files]|print message digests"
msgstr "|algo [files]|Message-Digests für die Dateien ausgeben"
-#: g10/g10.c:201
+#: g10/g10.c:204
msgid "print all message digests"
msgstr "Message-Digests für die Eingabedaten ausgeben"
-#: g10/g10.c:208
+#: g10/g10.c:211
msgid ""
"@\n"
"Options:\n"
" "
msgstr ""
"@\n"
"Optionen:\n"
" "
-#: g10/g10.c:210
+#: g10/g10.c:213
msgid "create ascii armored output"
msgstr "Ausgabe mit ASCII-Hülle versehen"
-#: g10/g10.c:212
+#: g10/g10.c:215
msgid "use this user-id to sign or decrypt"
msgstr "Mit dieser User-ID signieren"
-#: g10/g10.c:213
+#: g10/g10.c:216
msgid "use this user-id for encryption"
msgstr "Verschlüsseln für diese User-ID"
-#: g10/g10.c:214
+#: g10/g10.c:217
msgid "|N|set compress level N (0 disables)"
msgstr "Kompressionsstufe auf N setzen (0 = keine Kompr.)"
-#: g10/g10.c:216
+#: g10/g10.c:219
msgid "use canonical text mode"
msgstr "Textmodus benutzen"
-#: g10/g10.c:218
+#: g10/g10.c:221
msgid "use as output file"
msgstr "Als Ausgabedatei benutzen"
-#: g10/g10.c:219
+#: g10/g10.c:222
msgid "verbose"
msgstr "Detaillierte Informationen"
-#: g10/g10.c:220
+#: g10/g10.c:223
msgid "be somewhat more quiet"
msgstr "Etwas weniger Infos"
-#: g10/g10.c:221
+#: g10/g10.c:224
msgid "force v3 signatures"
msgstr "v3 Signaturen erzwingen"
#. { oDryRun, "dry-run", 0, N_("do not make any changes") },
-#: g10/g10.c:223
+#: g10/g10.c:226
msgid "batch mode: never ask"
msgstr "Stapelmodus: Keine Abfragen"
-#: g10/g10.c:224
+#: g10/g10.c:227
msgid "assume yes on most questions"
msgstr "\"Ja\" als Standardantwort annehmen"
-#: g10/g10.c:225
+#: g10/g10.c:228
msgid "assume no on most questions"
msgstr "\"Nein\" als Standardantwort annehmen"
-#: g10/g10.c:226
+#: g10/g10.c:229
msgid "add this keyring to the list of keyrings"
msgstr "Als öffentlichen Schlüsselbund mitbenutzen"
-#: g10/g10.c:227
+#: g10/g10.c:230
msgid "add this secret keyring to the list"
msgstr "Als geheimen Schlüsselbund mitbenutzen"
-#: g10/g10.c:228
+#: g10/g10.c:231
msgid "|NAME|use NAME as default secret key"
msgstr "|NAME|NAME als voreingestellten Schlüssel benutzen"
-#: g10/g10.c:229
+#: g10/g10.c:232
msgid "|NAME|set terminal charset to NAME"
msgstr "|NAME|Terminalzeichensatz NAME benutzen"
-#: g10/g10.c:230
+#: g10/g10.c:233
msgid "read options from file"
msgstr "Optionen aus der Datei lesen"
-#: g10/g10.c:232
+#: g10/g10.c:235
msgid "set debugging flags"
msgstr "Debug-Flags einschalten"
-#: g10/g10.c:233
+#: g10/g10.c:236
msgid "enable full debugging"
msgstr "Alle Debug-Flags einschalten"
-#: g10/g10.c:234
+#: g10/g10.c:237
msgid "|FD|write status info to this FD"
msgstr "|FD|Statusinfo auf FD (Dateihandle) ausgeben"
-#: g10/g10.c:235
+#: g10/g10.c:238
msgid "do not write comment packets"
msgstr "Keine Kommentarpakete schreiben"
-#: g10/g10.c:236
+#: g10/g10.c:239
msgid "(default is 1)"
msgstr "Benötigte Vollvertrauen (Voreinstellung 1)"
-#: g10/g10.c:237
+#: g10/g10.c:240
msgid "(default is 3)"
msgstr "Benötigte Teilvertrauen (Voreinstellung 3)"
-#: g10/g10.c:239
+#: g10/g10.c:242
msgid "|KEYID|ulimately trust this key"
msgstr "|KEYID|Diesem Schlüssel uneingeschränkt vertrauen"
-#: g10/g10.c:240
+#: g10/g10.c:243
msgid "|FILE|load extension module FILE"
msgstr "|FILE|Erweiterungsmodul DATEI laden"
-#: g10/g10.c:241
+#: g10/g10.c:244
msgid "emulate the mode described in RFC1991"
msgstr "Den in RFC1991 beschriebenen Modus nachahmen"
-#: g10/g10.c:242
+#: g10/g10.c:245
msgid "|N|use passphrase mode N"
msgstr "|N|Verwenden des Mantra-Modus N"
-#: g10/g10.c:244
+#: g10/g10.c:247
msgid "|NAME|use message digest algorithm NAME for passphrases"
msgstr "|NAME|Das Hashverfahren NAME für Mantras benutzen"
-#: g10/g10.c:246
+#: g10/g10.c:249
msgid "|NAME|use cipher algorithm NAME for passphrases"
msgstr "|NAME|Das Verschlü.verfahren NAME für Mantras benutzen"
-#: g10/g10.c:248
+#: g10/g10.c:251
msgid "|NAME|use cipher algorithm NAME"
msgstr "|NAME|Das Verschlü.verfahren NAME benutzen"
-#: g10/g10.c:249
+#: g10/g10.c:252
msgid "|NAME|use message digest algorithm NAME"
msgstr "|NAME|Das Hashverfahren NAME benutzen"
-#: g10/g10.c:250
+#: g10/g10.c:253
msgid "|N|use compress algorithm N"
msgstr "|N|Die Komprimierverfahren N benutzen"
-#: g10/g10.c:251
+#: g10/g10.c:254
msgid "throw keyid field of encrypted packets"
msgstr "entferne die AbsenderI-ID verschlüsselter Pakete"
-#: g10/g10.c:259
+#: g10/g10.c:262
msgid ""
"@\n"
"Examples:\n"
"\n"
" -se -r Bob [file] sign and encrypt for user Bob\n"
" --clearsign [file] make a clear text signature\n"
" --detach-sign [file] make a detached signature\n"
" --list-keys [names] show keys\n"
" --fingerprint [names] show fingerprints\n"
msgstr ""
"@\n"
"Beispiele:\n"
"\n"
" -se -r Bob [Datei] Signieren und verschlüsseln für Benutzer Bob\n"
" --clearsign [Datei] Eine Klartextsignatur erzeugen\n"
" --detach-sign [Datei] Eine abgetrennte Signatur erzeugen\n"
" --list-keys [Namen] Schlüssel anzeigen\n"
" --fingerprint [Namen] \"Fingerabdrücke\" anzeigen\n"
-#: g10/g10.c:337
+#: g10/g10.c:341
msgid "Please report bugs to <gnupg-bugs@gnu.org>.\n"
msgstr "Berichte über Wanzen (Programmfehler) bitte an <gnupg-bugs@gnu.org>.\n"
-#: g10/g10.c:342
+#: g10/g10.c:346
msgid "Usage: gpgm [options] [files] (-h for help)"
msgstr "Syntax: gpgm [Optionen] [Dateien] (-h für Hilfe)"
-#: g10/g10.c:344
+#: g10/g10.c:348
msgid "Usage: gpg [options] [files] (-h for help)"
msgstr "Aufruf: gpg [Optionen] [Dateien] (-h für Hilfe)"
-#: g10/g10.c:349
+#: g10/g10.c:353
msgid ""
"Syntax: gpgm [options] [files]\n"
"GnuPG maintenance utility\n"
msgstr ""
"Syntax: gpgm [options] [files]\n"
"GnuPG Wartungs-Hilfsprogramm\n"
-#: g10/g10.c:352
+#: g10/g10.c:356
msgid ""
"Syntax: gpg [options] [files]\n"
"sign, check, encrypt or decrypt\n"
"default operation depends on the input data\n"
msgstr ""
"Aufruf: gpg [Optionen] [Dateien]\n"
"Signieren, prüfen, verschlüsseln, entschlüsseln\n"
"Die voreingestellte Operation ist abhängig von den Eingabedaten\n"
-#: g10/g10.c:358
+#: g10/g10.c:362
msgid ""
"\n"
"Supported algorithms:\n"
msgstr ""
"\n"
"Unterstützte Verfahren:\n"
-#: g10/g10.c:433
+#: g10/g10.c:437
msgid "usage: gpgm [options] "
msgstr "Aufruf: gpgm [Optionen] "
-#: g10/g10.c:435
+#: g10/g10.c:439
msgid "usage: gpg [options] "
msgstr "Aufruf: gpg [Optionen] "
-#: g10/g10.c:476
+#: g10/g10.c:480
msgid "conflicting commands\n"
msgstr "Widersprüchliche Kommandos\n"
-#: g10/g10.c:614
+#: g10/g10.c:618
#, c-format
msgid "NOTE: no default option file '%s'\n"
msgstr "Hinweis: Keine voreingestellte Optionendatei '%s' vorhanden\n"
-#: g10/g10.c:618
+#: g10/g10.c:622
#, c-format
msgid "option file '%s': %s\n"
msgstr "Optionendatei '%s': %s\n"
-#: g10/g10.c:625
+#: g10/g10.c:629
#, c-format
msgid "reading options from '%s'\n"
msgstr "Optionen werden aus '%s' gelesen\n"
-#: g10/g10.c:773
+#: g10/g10.c:782
#, c-format
msgid "%s is not a valid character set\n"
msgstr "%s ist kein gültiger Zeichensatz.\n"
-#: g10/g10.c:807 g10/g10.c:819
+#: g10/g10.c:817 g10/g10.c:829
msgid "selected cipher algorithm is invalid\n"
msgstr "Das ausgewählte Verschlüsslungsverfahren ist ungültig\n"
-#: g10/g10.c:813 g10/g10.c:825
+#: g10/g10.c:823 g10/g10.c:835
msgid "selected digest algorithm is invalid\n"
msgstr "Das ausgewählte Hashverfahren ist ungültig\n"
-#: g10/g10.c:828
+#: g10/g10.c:838
#, c-format
msgid "compress algorithm must be in range %d..%d\n"
msgstr "Das Komprimierverfahren muß im Bereich %d bis %d liegen\n"
-#: g10/g10.c:830
+#: g10/g10.c:840
msgid "completes-needed must be greater than 0\n"
msgstr "completes-needed müssen größer als 0 sein\n"
-#: g10/g10.c:832
+#: g10/g10.c:842
msgid "marginals-needed must be greater than 1\n"
msgstr "marginals-needed müssen größer als 1 sein\n"
-#: g10/g10.c:834
+#: g10/g10.c:844
msgid "max-cert-depth must be in range 1 to 255\n"
msgstr "max-cert-depth muß im Bereich 1 bis 255 liegen\n"
-#: g10/g10.c:837
+#: g10/g10.c:847
msgid "NOTE: simple S2K mode (0) is strongly discouraged\n"
msgstr "Hinweis: Vom \"simple S2K\"-Modus (0) ist strikt abzuraten\n"
-#: g10/g10.c:841
+#: g10/g10.c:851
msgid "invalid S2K mode; must be 0, 1 or 3\n"
msgstr "ungültiger \"simple S2K\"-Modus; Wert muß 0, 1 oder 3 sein\n"
-#: g10/g10.c:924
+#: g10/g10.c:934
#, c-format
msgid "failed to initialize the TrustDB: %s\n"
msgstr "Die Trust-DB kann nicht initialisiert werden: %s\n"
-#: g10/g10.c:930
+#: g10/g10.c:940
msgid "--store [filename]"
msgstr "--store [Dateiname]"
-#: g10/g10.c:938
+#: g10/g10.c:948
msgid "--symmetric [filename]"
msgstr "--symmetric [Dateiname]"
-#: g10/g10.c:946
+#: g10/g10.c:956
msgid "--encrypt [filename]"
msgstr "--encrypt [Dateiname]"
-#: g10/g10.c:959
+#: g10/g10.c:969
msgid "--sign [filename]"
msgstr "--sign [Dateiname]"
-#: g10/g10.c:972
+#: g10/g10.c:982
msgid "--sign --encrypt [filename]"
msgstr "--sign --encrypt [Dateiname]"
-#: g10/g10.c:986
+#: g10/g10.c:996
msgid "--clearsign [filename]"
msgstr "--clearsign [Dateiname]"
-#: g10/g10.c:998
+#: g10/g10.c:1008
msgid "--decrypt [filename]"
msgstr "--decrypt [Dateiname]"
-#: g10/g10.c:1007
+#: g10/g10.c:1017
msgid "--edit-key username [commands]"
msgstr "--edit-key Username [Befehle]"
-#: g10/g10.c:1023
+#: g10/g10.c:1033
msgid "--delete-secret-key username"
msgstr "--delete-secret-key Username"
-#: g10/g10.c:1026
+#: g10/g10.c:1036
msgid "--delete-key username"
msgstr "--delete-key Benutzername"
-#: g10/encode.c:216 g10/g10.c:1049 g10/sign.c:301
+#: g10/encode.c:216 g10/g10.c:1059 g10/sign.c:301
#, c-format
msgid "can't open %s: %s\n"
msgstr "'%s' kann nicht geöffnet werden: %s\n"
-#: g10/g10.c:1060
+#: g10/g10.c:1070
msgid "-k[v][v][v][c] [userid] [keyring]"
msgstr "-k[v][v][v][c] [Benutzername] [Keyring]"
-#: g10/g10.c:1116
+#: g10/g10.c:1127
#, c-format
msgid "dearmoring failed: %s\n"
msgstr "Entfernen der ASCII-Hülle ist fehlgeschlagen: %s\n"
-#: g10/g10.c:1124
+#: g10/g10.c:1135
#, c-format
msgid "enarmoring failed: %s\n"
msgstr "Anbringen der ASCII-Hülle ist fehlgeschlagen: %s\n"
-#: g10/g10.c:1190
+#: g10/g10.c:1201
#, c-format
msgid "invalid hash algorithm '%s'\n"
msgstr "Ungültiges Hashverfahren '%s'\n"
-#: g10/g10.c:1269
+#: g10/g10.c:1280
msgid "[filename]"
msgstr "[Dateiname]"
-#: g10/g10.c:1273
+#: g10/g10.c:1284
msgid "Go ahead and type your message ...\n"
msgstr "Auf geht's - Botschaft eintippen ...\n"
-#: g10/decrypt.c:59 g10/g10.c:1276 g10/verify.c:66
+#: g10/decrypt.c:59 g10/g10.c:1287 g10/verify.c:66
#, c-format
msgid "can't open '%s'\n"
msgstr "'%s' kann nicht geöffnet werden\n"
-#: g10/g10.c:1325
-msgid ""
-"RSA keys are deprecated; please consider creating a new key and use this key "
-"in the future\n"
-msgstr ""
-"RSA Schlüssel sind nicht erwünscht; bitte denken Sie darüber nach, einen\n"
-"neuen Schlüssel zu erzeugen und diesen in Zukunft zu benutzen\n"
-
#: g10/armor.c:344 g10/armor.c:391
msgid "armor header: "
msgstr "ASCII-Hülle: "
#: g10/armor.c:355
msgid "invalid clearsig header\n"
msgstr "Ungültige Klartextsignatur-Einleitung\n"
#: g10/armor.c:382
msgid "invalid armor header: "
msgstr "Ungültige ASCII-Hülle"
#: g10/armor.c:460
#, c-format
msgid "armor: %s\n"
msgstr "ASCII-Hülle: %s\n"
#: g10/armor.c:533
msgid "invalid dash escaped line: "
msgstr "Ungültige mit Bindestrich \"escapte\" Zeile: "
#: g10/armor.c:602
msgid "invalid clear text header: "
msgstr "ungültige Klartexteinleitung"
#: g10/armor.c:845
#, c-format
msgid "invalid radix64 character %02x skipped\n"
msgstr "Ungültiges \"radix64\" Zeichen %02x ignoriert\n"
#: g10/armor.c:878
msgid "premature eof (no CRC)\n"
msgstr "vorzeitiges Dateiende (keine Prüfsumme)\n"
#: g10/armor.c:897
msgid "premature eof (in CRC)\n"
msgstr "vorzeitiges Dateiende (innerhalb der Prüfsumme)\n"
#: g10/armor.c:901
msgid "malformed CRC\n"
msgstr "Falsch aufgebaute Prüfsumme\n"
#: g10/armor.c:905
#, c-format
msgid "CRC error; %06lx - %06lx\n"
msgstr "Prüfsummenfehler; %06lx - %06lx\n"
#: g10/armor.c:924
msgid "premature eof (in Trailer)\n"
msgstr "vorzeitiges Dateiende (im Nachsatz)\n"
#: g10/armor.c:928
msgid "error in trailer line\n"
msgstr "Fehler in der Nachsatzzeile\n"
#: g10/armor.c:1182
msgid "no valid RFC1991 or OpenPGP data found.\n"
msgstr "Keine gültigen RFC1991- oder OpenPGP-Daten gefunden.\n"
-#: g10/pkclist.c:121
+#: g10/pkclist.c:138
#, c-format
msgid ""
"No trust value assigned to %lu:\n"
"%4u%c/%08lX %s \""
msgstr ""
"Es ist kein \"Owner trust\" für %lu definiert:\n"
"%4u%c/%08lX %s \""
-#: g10/pkclist.c:131
+#: g10/pkclist.c:148
msgid ""
"Please decide how far you trust this user to correctly\n"
"verify other users' keys (by looking at passports,\n"
"checking fingerprints from different sources...)?\n"
"\n"
" 1 = Don't know\n"
" 2 = I do NOT trust\n"
" 3 = I trust marginally\n"
" 4 = I trust fully\n"
" s = please show me more information\n"
msgstr ""
"Bitte entscheiden Sie, in wieweit Sie diesem User zutrauen,\n"
"den Schlüssel eines anderen Users korrekt zu prüfen (Vergleich mit\n"
"Lictbildausweisen, Vergleich der Fingerabdrücke aus unterschiedlichen\n"
"Quellen ...)?\n"
"\n"
" 1 = Weiß nicht so recht\n"
" 2 = Neeh, dem traue ich das nicht zu\n"
" 3 = Ich vertraue ihm normalerweise\n"
" 4 = Ich vertraue ihm vollständig\n"
" s = Bitte weitere Information anzeigen\n"
-#: g10/pkclist.c:140
+#: g10/pkclist.c:157
msgid " m = back to the main menu\n"
msgstr " m = Zurück zum Menü\n"
+#: g10/pkclist.c:159
+msgid " q = quit\n"
+msgstr " q = Beenden\n"
+
# valid user replies (not including 1..4)
#. a string with valid answers
-#: g10/pkclist.c:145
-msgid "sSmM"
-msgstr "sSmM"
+#: g10/pkclist.c:164
+#, fuzzy
+msgid "sSmMqQ"
+msgstr "sSmMqQ"
-#: g10/pkclist.c:149
+#: g10/pkclist.c:168
msgid "Your decision? "
msgstr "Ihre Auswahl? "
-#: g10/pkclist.c:169
+#: g10/pkclist.c:188
msgid "Certificates leading to an ultimately trusted key:\n"
msgstr "Zertifikate führen zu einem letztlich vertrauenswürdigen Schlüssel:\n"
-#: g10/pkclist.c:197
+#: g10/pkclist.c:221
msgid ""
"Could not find a valid trust path to the key. Let's see whether we\n"
"can assign some missing owner trust values.\n"
"\n"
msgstr ""
"Für diesen Schlüssel konnte kein gültiger \"Trust Path\" gefunden werden.\n"
"Mal sehen, ob wir sonst irgendwie ein paar fehlende \"Owner trust\" Werte \n"
"ermitteln können.\n"
"\n"
-#: g10/pkclist.c:219
+#: g10/pkclist.c:251
msgid ""
"No path leading to one of our keys found.\n"
"\n"
msgstr ""
"Kein Pfad führt zu einen unserer Schlüsseln.\n"
"\n"
-#: g10/pkclist.c:221
+#: g10/pkclist.c:253
msgid ""
"No certificates with undefined trust found.\n"
"\n"
msgstr ""
"Keine Zertifikate mit undefinierten Vertrauen gefunden.\n"
"\n"
-#: g10/pkclist.c:223
+#: g10/pkclist.c:255
msgid ""
"No trust values changed.\n"
"\n"
msgstr ""
"Keine \"trust\" Werte geändert.\n"
"\n"
-#: g10/pkclist.c:238
+#: g10/pkclist.c:270
#, c-format
msgid "key %08lX: key has been revoked!\n"
msgstr "Schlüssel %08lX: Schlüssel wurde widerrufen\n"
-#: g10/pkclist.c:244 g10/pkclist.c:335
+#: g10/pkclist.c:276 g10/pkclist.c:369
msgid "Use this key anyway? "
msgstr "Diesen Schlüssel trotzdem benutzen?"
-#: g10/pkclist.c:266
+#: g10/pkclist.c:298
#, c-format
msgid "%08lX: key has expired\n"
msgstr "%08lX: Schlüssel ist verfallen!\n"
-#: g10/pkclist.c:272
+#: g10/pkclist.c:304
#, c-format
msgid "%08lX: no info to calculate a trust probability\n"
msgstr ""
"%08lX: Keine Infos zur Berechnung der Vertrauenswahrscheinlichkeit "
"vorgefunden\n"
-#: g10/pkclist.c:288
+#: g10/pkclist.c:322
#, c-format
msgid "%08lX: We do NOT trust this key\n"
msgstr "%08lX: Wir haben KEIN Vertrauen zu diesem Schlüssel!\n"
-#: g10/pkclist.c:294
+#: g10/pkclist.c:328
#, c-format
msgid ""
"%08lX: It is not sure that this key really belongs to the owner\n"
"but it is accepted anyway\n"
msgstr ""
"%08lX: Es ist nicht sicher, daß dieser Schlüssel wirklich dem vorgeblichen\n"
"Besitzer gehört, aber er wird trotzdem akzeptiert\n"
-#: g10/pkclist.c:300
+#: g10/pkclist.c:334
msgid "This key probably belongs to the owner\n"
msgstr ""
"Dieser Schlüssel gehört uns (alldieweil wir den geheimen Schlüssel dazu "
"haben)\n"
-#: g10/pkclist.c:305
+#: g10/pkclist.c:339
msgid "This key belongs to us\n"
msgstr ""
"Dieser Schlüssel gehört uns (alldieweil wir den geheimen Schlüssel dazu "
"haben)\n"
-#: g10/pkclist.c:330
+#: g10/pkclist.c:364
msgid ""
"It is NOT certain that the key belongs to its owner.\n"
"If you *really* know what you are doing, you may answer\n"
"the next question with yes\n"
"\n"
msgstr ""
"Es ist NICHT sicher, daß der Schlüssel dem vorgeblichen Besitzer gehört.\n"
"Wenn Sie *wirklich* wissen, was Sie tun, können Sie die nächste\n"
"Frage mit ja beantworten\n"
-#: g10/pkclist.c:339
+#: g10/pkclist.c:373
msgid "WARNING: Using untrusted key!\n"
msgstr "WARNUNG: Ein Schlüssel ohne gesichertes Vertrauen wird benutzt!\n"
-#: g10/pkclist.c:375
+#: g10/pkclist.c:409
msgid "WARNING: This key has been revoked by its owner!\n"
msgstr "WARNUNG: Dieser Schlüssel wurde von seinem Besitzer widerrufen!\n"
-#: g10/pkclist.c:376
+#: g10/pkclist.c:410
msgid " This could mean that the signature is forgery.\n"
msgstr " Das könnte bedeuten, daß die Signatur gefälscht ist.\n"
-#: g10/pkclist.c:397
+#: g10/pkclist.c:431
msgid "Note: This key has expired!\n"
msgstr "Hinweis: Dieser Schlüssel ist verfallen!\n"
-#: g10/pkclist.c:404
+#: g10/pkclist.c:438
msgid "WARNING: This key is not certified with a trusted signature!\n"
msgstr "WARNUNG: Dieser Schlüssel trägt keine vertrauenswürdige Signatur!\n"
-#: g10/pkclist.c:406
+#: g10/pkclist.c:440
msgid ""
" There is no indication that the signature belongs to the owner.\n"
msgstr ""
" Es gibt keinen Hinweis, daß die Signatur wirklich dem vorgeblichen "
"Besitzer gehört.\n"
-#: g10/pkclist.c:421
+#: g10/pkclist.c:456
msgid "WARNING: We do NOT trust this key!\n"
msgstr "WARNUNG: Wir haben KEIN Vertrauen zu diesem Schlüssel!\n"
-#: g10/pkclist.c:422
+#: g10/pkclist.c:457
msgid " The signature is probably a FORGERY.\n"
msgstr " Die Signatur ist wahrscheinlich eine FÄLSCHUNG.\n"
-#: g10/pkclist.c:429
+#: g10/pkclist.c:464
msgid ""
"WARNING: This key is not certified with sufficiently trusted signatures!\n"
msgstr ""
"WARNUNG: Dieser Schlüssel ist nicht durch hinreichend vertrauenswürdige "
"Signaturen zertifiziert!\n"
-#: g10/pkclist.c:432
+#: g10/pkclist.c:467
msgid " It is not certain that the signature belongs to the owner.\n"
msgstr ""
" Es ist nicht sicher, daß die Signatur wirklich dem vorgeblichen "
"Besitzer gehört.\n"
-#: g10/pkclist.c:477
+#: g10/pkclist.c:512
msgid ""
"You did not specify a user ID. (you may use \"-r\")\n"
"\n"
msgstr ""
"Sie gaben keine User-ID angegeben (Benutzen Sie die Option \"-r\").\n"
"\n"
-#: g10/pkclist.c:482
+#: g10/pkclist.c:517
msgid "Enter the user ID: "
msgstr "Geben Sie die User-ID ein: "
-#: g10/pkclist.c:493
+#: g10/pkclist.c:528
msgid "No such user ID.\n"
msgstr "Keine solche User-ID vorhanden.\n"
-#: g10/pkclist.c:527 g10/pkclist.c:554
+#: g10/pkclist.c:562 g10/pkclist.c:589
#, c-format
msgid "%s: skipped: %s\n"
msgstr "%s: übersprungen: %s\n"
-#: g10/pkclist.c:535
+#: g10/pkclist.c:570
#, c-format
msgid "%s: error checking key: %s\n"
msgstr "%s: Fehler beim Prüfen des Schlüssels: %s\n"
-#: g10/pkclist.c:561
+#: g10/pkclist.c:596
msgid "no valid addressees\n"
msgstr "Keine gültigen Adressaten\n"
#: g10/keygen.c:124
msgid "writing self signature\n"
msgstr "Die Eigenbeglaubigung wird geschrieben\n"
#: g10/keygen.c:162
msgid "writing key binding signature\n"
msgstr "Schreiben der \"key-binding\" Signatur\n"
#: g10/keygen.c:388
msgid "Please select what kind of key you want:\n"
msgstr "Bitte wählen Sie, welche Art von Schlüssel Sie möchten:\n"
#: g10/keygen.c:390
#, c-format
msgid " (%d) DSA and ElGamal (default)\n"
msgstr " (%d) DSA und ElGamal (voreingestellt)\n"
#: g10/keygen.c:391
#, c-format
-msgid " (%d) ElGamal (sign and encrypt)\n"
-msgstr " (%d) ElGamal (signieren/beglaubigen und verschlüsseln)\n"
+msgid " (%d) DSA (sign only)\n"
+msgstr " (%d) DSA (nur signieren/beglaubigen)\n"
#: g10/keygen.c:393
#, c-format
msgid " (%d) ElGamal (encrypt only)\n"
msgstr " (%d) ElGamal (nur verschlüsseln)\n"
#: g10/keygen.c:394
#, c-format
-msgid " (%d) DSA (sign only)\n"
-msgstr " (%d) DSA (nur signieren/beglaubigen)\n"
+msgid " (%d) ElGamal (sign and encrypt)\n"
+msgstr " (%d) ElGamal (signieren/beglaubigen und verschlüsseln)\n"
-#: g10/keygen.c:395
+#: g10/keygen.c:396
#, c-format
msgid " (%d) ElGamal in a v3 packet\n"
msgstr " (%d) ElGamal in einem v3-Paket\n"
-#: g10/keygen.c:399
+#: g10/keygen.c:401
msgid "Your selection? "
msgstr "Ihre Auswahl? "
-#: g10/keygen.c:425
+#: g10/keygen.c:411
+#, fuzzy
+msgid "Do you really want to create a sign and encrypt key? "
+msgstr "Möchten Sie die ausgewählten Schlüssel wirklich entfernen? "
+
+#: g10/keygen.c:432
msgid "Invalid selection.\n"
msgstr "Ungültige Auswahl.\n"
-#: g10/keygen.c:437
+#: g10/keygen.c:444
#, c-format
msgid ""
"About to generate a new %s keypair.\n"
" minimum keysize is 768 bits\n"
" default keysize is 1024 bits\n"
" highest suggested keysize is 2048 bits\n"
msgstr ""
"Es wird ein neues %s Schlüsselpaar erzeugt.\n"
" kleinste Schlüssellänge ist 768 Bit\n"
" standard Schlüssellänge ist 1024 Bit\n"
" größte sinnvolle Schlüssellänge ist 2048 Bit\n"
-#: g10/keygen.c:444
+#: g10/keygen.c:451
msgid "What keysize do you want? (1024) "
msgstr "Welche Schlüssellänge wünschen Sie? (1024) "
-#: g10/keygen.c:449
+#: g10/keygen.c:456
msgid "DSA only allows keysizes from 512 to 1024\n"
msgstr "DSA erlaubt nur Schlüssellängen von 512 bis 1024\n"
-#: g10/keygen.c:451
+#: g10/keygen.c:458
msgid "keysize too small; 768 is smallest value allowed.\n"
msgstr "zu kurz; 768 ist die kleinste mögliche Schlüssellänge.\n"
-#: g10/keygen.c:454
+#: g10/keygen.c:461
msgid ""
"Keysizes larger than 2048 are not suggested because\n"
"computations take REALLY long!\n"
msgstr ""
"Schlüssellängen größer als 2048 werden nicht empfohlen, da die\n"
"Berechnungen dann WIRKLICH lange brauchen!\n"
-#: g10/keygen.c:457
+#: g10/keygen.c:464
msgid "Are you sure that you want this keysize? "
msgstr "Sind Sie sicher, daß Sie diese Schlüssellänge wünschen? "
-#: g10/keygen.c:458
+#: g10/keygen.c:465
msgid ""
"Okay, but keep in mind that your monitor and keyboard radiation is also very "
"vulnerable to attacks!\n"
msgstr ""
"Gut, aber bitte denken Sie auch daran, daß Monitor und Tastatur Daten "
"abstrahlen und diese leicht mitgelesen werden können.\n"
-#: g10/keygen.c:466
+#: g10/keygen.c:473
msgid "Do you really need such a large keysize? "
msgstr "Brauchen Sie wirklich einen derartig langen Schlüssel? "
-#: g10/keygen.c:472
+#: g10/keygen.c:479
#, c-format
msgid "Requested keysize is %u bits\n"
msgstr "Die verlangte Schlüssellänge beträgt %u Bit\n"
-#: g10/keygen.c:475 g10/keygen.c:479
+#: g10/keygen.c:482 g10/keygen.c:486
#, c-format
msgid "rounded up to %u bits\n"
msgstr "aufgerundet auf %u Bit\n"
-#: g10/keygen.c:492
+#: g10/keygen.c:499
msgid ""
"Please specify how long the key should be valid.\n"
" 0 = key does not expire\n"
" <n> = key expires in n days\n"
" <n>w = key expires in n weeks\n"
" <n>m = key expires in n months\n"
" <n>y = key expires in n years\n"
msgstr ""
"Bitte wählen Sie, wie lange der Schlüssel gültig bleiben soll.\n"
" 0 = Schlüssel verfällt nie\n"
" <n> = Schlüssel verfällt nach n Tagen\n"
" <n>w = Schlüssel verfällt nach n Wochen\n"
" <n>m = Schlüssel verfällt nach n Monaten\n"
" <n>y = Schlüssel verfällt nach n Jahren\n"
-#: g10/keygen.c:507
+#: g10/keygen.c:514
msgid "Key is valid for? (0) "
msgstr "Der Schlüssel bleibt wie lange gültig? (0) "
-#: g10/keygen.c:518
+#: g10/keygen.c:525
msgid "invalid value\n"
msgstr "Ungültiger Wert.\n"
-#: g10/keygen.c:523
+#: g10/keygen.c:530
msgid "Key does not expire at all\n"
msgstr "Der Schlüssel verfällt nie.\n"
#. print the date when the key expires
-#: g10/keygen.c:529
+#: g10/keygen.c:536
#, c-format
msgid "Key expires at %s\n"
msgstr "Der Schlüssel verfällt am %s\n"
-#: g10/keygen.c:535
+#: g10/keygen.c:542
msgid "Is this correct (y/n)? "
msgstr "Ist dies richtig? (j/n) "
-#: g10/keygen.c:577
+#: g10/keygen.c:584
msgid ""
"\n"
"You need a User-ID to identify your key; the software constructs the user "
"id\n"
"from Real Name, Comment and Email Address in this form:\n"
" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n"
"\n"
msgstr ""
"\n"
"Sie benötigen eine User-ID, um Ihren Schlüssel eindeutig zu machen; das\n"
"Programm baut diese User-ID aus Ihrem echten Namen, einem Kommentar und\n"
"Ihrer E-Mail-Adresse in dieser Form auf:\n"
" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n"
"\n"
-#: g10/keygen.c:588
+#: g10/keygen.c:595
msgid "Real name: "
msgstr "Ihr Name (\"Vorname Nachname\"): "
-#: g10/keygen.c:592
+#: g10/keygen.c:599
msgid "Invalid character in name\n"
msgstr "Ungültiges Zeichen im Namen\n"
-#: g10/keygen.c:594
+#: g10/keygen.c:601
msgid "Name may not start with a digit\n"
msgstr "Der Name darf nicht mit einer Ziffer beginnen.\n"
-#: g10/keygen.c:596
+#: g10/keygen.c:603
msgid "Name must be at least 5 characters long\n"
msgstr "Der Name muß min. 5 Zeichen lang sein.\n"
-#: g10/keygen.c:604
+#: g10/keygen.c:611
msgid "Email address: "
msgstr "E-Mail-Adresse: "
-#: g10/keygen.c:616
+#: g10/keygen.c:623
msgid "Not a valid email address\n"
msgstr "Diese E-Mail-Adresse ist ungültig\n"
-#: g10/keygen.c:624
+#: g10/keygen.c:631
msgid "Comment: "
msgstr "Kommentar: "
-#: g10/keygen.c:630
+#: g10/keygen.c:637
msgid "Invalid character in comment\n"
msgstr "Ungültiges Zeichen im Kommentar.\n"
-#: g10/keygen.c:650
+#: g10/keygen.c:657
#, c-format
msgid ""
"You selected this USER-ID:\n"
" \"%s\"\n"
"\n"
msgstr ""
"Sie haben diese User-ID gewählt:\n"
" \"%s\"\n"
"\n"
-#: g10/keygen.c:653
+#: g10/keygen.c:660
msgid "NnCcEeOoQq"
msgstr "NnKkEeFfBb"
-#: g10/keygen.c:663
+#: g10/keygen.c:670
msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? "
msgstr "Ändern: (N)ame, (K)ommentar, (E)-Mail oder (F)ertig/(B)eenden? "
-#: g10/keygen.c:715
+#: g10/keygen.c:722
msgid ""
"You need a Passphrase to protect your secret key.\n"
"\n"
msgstr ""
"Sie benötigen ein Mantra, um den geheimen Schlüssel zu schützen.\n"
"\n"
-#: g10/keyedit.c:389 g10/keygen.c:723
+#: g10/keyedit.c:389 g10/keygen.c:730
msgid "passphrase not correctly repeated; try again.\n"
msgstr "Mantra wurde nicht richtig wiederholt; noch einmal versuchen.\n"
-#: g10/keygen.c:729
+#: g10/keygen.c:736
msgid ""
"You don't want a passphrase - this is probably a *bad* idea!\n"
"I will do it anyway. You can change your passphrase at any time,\n"
"using this program with the option \"--edit-key\".\n"
"\n"
msgstr ""
"Sie möchten kein Mantra - Dies ist *nicht* zu empfehlen!\n"
"Es ist trotzdem möglich. Sie können Ihr Mantra jederzeit\n"
"ändern, indem sie dieses Programm mit dem Kommando \"--edit-key\"\n"
"aufrufen.\n"
"\n"
-#: g10/keygen.c:750
+#: g10/keygen.c:757
msgid ""
"We need to generate a lot of random bytes. It is a good idea to perform\n"
"some other action (work in another window, move the mouse, utilize the\n"
"network and the disks) during the prime generation; this gives the random\n"
"number generator a better chance to gain enough entropy.\n"
msgstr ""
"Wir müßen eine ganze Menge Zufallszahlen erzeugen. Sie können dies\n"
"unterstützen, indem Sie z.B. in einem anderen Fenster/Konsole irgendetwas\n"
"tippen oder irgendwelche anderen Programme benutzen.\n"
-#: g10/keygen.c:820
+#: g10/keygen.c:827
msgid "Key generation can only be used in interactive mode\n"
msgstr ""
"Die Schlüsselerzeugung kann nur im interaktiven Modus benutzt werden.\n"
-#: g10/keygen.c:828
+#: g10/keygen.c:835
msgid "DSA keypair will have 1024 bits.\n"
msgstr "Der DSA Schlüssel wird 1024 Bits haben.\n"
-#: g10/keygen.c:834
+#: g10/keygen.c:841
msgid "Key generation cancelled.\n"
msgstr "Schlüsselerzeugung abgebrochen.\n"
-#: g10/keygen.c:844
+#: g10/keygen.c:851
#, c-format
msgid "writing public certificate to '%s'\n"
msgstr "schreiben des öffentlichen Schlüssels nach '%s'\n"
-#: g10/keygen.c:845
+#: g10/keygen.c:852
#, c-format
msgid "writing secret certificate to '%s'\n"
msgstr "schreiben des geheimen Schlüssels nach '%s'\n"
-#: g10/keygen.c:922
+#: g10/keygen.c:929
msgid "public and secret key created and signed.\n"
msgstr "Öffentlichen und geheimen Schlüssel erzeugt und signiert.\n"
-#: g10/keygen.c:924
+#: g10/keygen.c:931
msgid ""
"Note that this key cannot be used for encryption. You may want to use\n"
"the command \"--add-key\" to generate a secondary key for this purpose.\n"
msgstr ""
"Bitte beachten Sie, daß dieser Schlüssel nicht zum Verschlüsseln benutzt\n"
"werden kann. Sie können aber mit dem Kommando \"--add-key\" einen\n"
"Zweitschlüssel zu diesem Schlüssel hinzufügen.\n"
-#: g10/keygen.c:938 g10/keygen.c:1023
+#: g10/keygen.c:945 g10/keygen.c:1030
#, c-format
msgid "Key generation failed: %s\n"
msgstr "Schlüsselerzeugung fehlgeschlagen: %s\n"
-#: g10/keygen.c:1001
+#: g10/keygen.c:1008
msgid "Really create? "
msgstr "Wirklich erzeugen? "
#: g10/encode.c:88 g10/openfile.c:81 g10/openfile.c:158 g10/tdbio.c:445
#: g10/tdbio.c:504
#, c-format
msgid "%s: can't open: %s\n"
msgstr "%s: kann nicht geöffnet werden: %s\n"
#: g10/encode.c:107
#, c-format
msgid "error creating passphrase: %s\n"
msgstr "Fehler beim Erzeugen des Mantras: %s\n"
#: g10/encode.c:155 g10/encode.c:269
#, c-format
msgid "%s: WARNING: empty file\n"
msgstr "%s: WARNUNG: Leere Datei\n"
#: g10/encode.c:222
#, c-format
msgid "reading from '%s'\n"
msgstr "Lesen von '%s'\n"
#: g10/encode.c:397
-#, c-format
-msgid "%s encrypted for: %s\n"
+#, fuzzy, c-format
+msgid "%s/%s encrypted for: %s\n"
msgstr "%s verschlüsselt für: %s\n"
-#: g10/export.c:162
+#: g10/export.c:114
+#, fuzzy, c-format
+msgid "%s: user not found: %s\n"
+msgstr "%s: Benutzer nicht gefunden\n"
+
+#: g10/export.c:123
+#, fuzzy, c-format
+msgid "certificate read problem: %s\n"
+msgstr "User '%s' Leseproblem: %s\n"
+
+#: g10/export.c:132
+#, fuzzy, c-format
+msgid "key %08lX: not a rfc2440 key - skipped\n"
+msgstr ""
+"Schlüssel %08lX: kein öffentlicher Schüssel für vertrauenswürdigen Schlüssel "
+"- übersprungen\n"
+
+#: g10/export.c:174
msgid "WARNING: nothing exported\n"
msgstr "WARNUNG: Nichts exportiert\n"
#: g10/getkey.c:164
msgid "too many entries in pk cache - disabled\n"
msgstr "zu viele Einträge im pk-Lager - abgeschaltet\n"
#: g10/getkey.c:263
msgid "too many entries in unk cache - disabled\n"
msgstr "zu viele Einträge im unk-Lager - abgeschaltet\n"
#: g10/getkey.c:989
#, c-format
msgid "using secondary key %08lX instead of primary key %08lX\n"
msgstr ""
"der Zweitschlüssel %08lX wird anstelle des Hauptschlüssels %08lX verwendet\n"
-#: g10/import.c:129 g10/trustdb.c:1166
+#: g10/import.c:129 g10/trustdb.c:1180
#, c-format
msgid "can't open file: %s\n"
msgstr "Kann die Datei nicht öffnen: %s\n"
#: g10/import.c:145
#, c-format
msgid "skipping block of type %d\n"
msgstr "überspringe den Block vom Typ %d\n"
-#: g10/import.c:152 g10/trustdb.c:1425 g10/trustdb.c:1494
+#: g10/import.c:152 g10/trustdb.c:1474 g10/trustdb.c:1543
#, c-format
msgid "%lu keys so far processed\n"
msgstr "%lu Schlüssel bislang bearbeitet\n"
-#: g10/import.c:157 g10/trustdb.c:1242
+#: g10/import.c:157 g10/trustdb.c:1256
#, c-format
msgid "read error: %s\n"
msgstr "Lesefehler: %s\n"
#: g10/import.c:159
#, c-format
msgid "Total number processed: %lu\n"
msgstr "Anzahl insgesamt bearbeiteter Schlüssel: %lu\n"
#: g10/import.c:161
#, c-format
msgid " w/o user IDs: %lu\n"
msgstr " ohne User-ID: %lu\n"
#: g10/import.c:163
#, c-format
msgid " imported: %lu"
msgstr " importiert: %lu"
#: g10/import.c:169
#, c-format
msgid " unchanged: %lu\n"
msgstr " unverändert: %lu\n"
#: g10/import.c:171
#, c-format
msgid " new user IDs: %lu\n"
msgstr " neue User-IDs: %lu\n"
#: g10/import.c:173
#, c-format
msgid " new subkeys: %lu\n"
msgstr " neue Unterschlüssel: %lu\n"
#: g10/import.c:175
#, c-format
msgid " new signatures: %lu\n"
msgstr " neue Signaturen: %lu\n"
#: g10/import.c:177
#, c-format
msgid " new key revocations: %lu\n"
msgstr "neue Schlüsselwiderrufe: %lu\n"
#: g10/import.c:179
#, c-format
msgid " secret keys read: %lu\n"
msgstr " gelesene geheime Schl.: %lu\n"
#: g10/import.c:181
#, c-format
msgid " secret keys imported: %lu\n"
msgstr "geheime Schlüssel importiert: %lu\n"
#: g10/import.c:183
#, c-format
msgid " secret keys unchanged: %lu\n"
msgstr " unveränderte geh.Schl.: %lu\n"
#: g10/import.c:325 g10/import.c:517
#, c-format
msgid "key %08lX: no user id\n"
msgstr "Schlüssel %08lX: Keine User-ID\n"
#: g10/import.c:336
#, c-format
msgid "key %08lX: no valid user ids\n"
msgstr "Schlüssel %08lX: Keine gültigen User-IDs\n"
#: g10/import.c:338
msgid "this may be caused by a missing self-signature\n"
msgstr "dies könnte durch fehlende Eigenbeglaubigung verursacht worden sein\n"
#: g10/import.c:349 g10/import.c:585
#, c-format
msgid "key %08lX: public key not found: %s\n"
msgstr "Schlüssel %08lX: Öffentlicher Schlüssel nicht gefunden: %s\n"
#: g10/import.c:355
msgid "no default public keyring\n"
msgstr "Kein voreingestellter öffentlicher Schlüsselbund\n"
-#: g10/import.c:359 g10/openfile.c:105 g10/sign.c:205 g10/sign.c:563
+#: g10/import.c:359 g10/openfile.c:105 g10/sign.c:205 g10/sign.c:592
#, c-format
msgid "writing to '%s'\n"
msgstr "Schreiben nach '%s'\n"
#: g10/import.c:363 g10/import.c:423 g10/import.c:639
#, c-format
msgid "can't lock public keyring: %s\n"
msgstr "kann öffentlichen Schlüsselbund nicht sperren: %s\n"
#: g10/import.c:366
#, c-format
msgid "can't write to keyring: %s\n"
msgstr "kann Schlüsselbund nicht schreiben: %s\n"
#: g10/import.c:370
#, c-format
msgid "key %08lX: public key imported\n"
msgstr "Schlüssel %08lX: Öffentlicher Schlüssel importiert\n"
#: g10/import.c:383
#, c-format
msgid "key %08lX: doesn't match our copy\n"
msgstr "Schlüssel %08lX: Stimmt nicht mit unserer Kopie überein\n"
#: g10/import.c:396 g10/import.c:594
#, c-format
msgid "key %08lX: can't locate original keyblock: %s\n"
msgstr ""
-"Schlüssel %08lX: der lokale originale Schlüsselblocks wurde nicht gefunden: %s\n"
+"Schlüssel %08lX: der lokale originale Schlüsselblocks wurde nicht gefunden: "
+"%s\n"
#: g10/import.c:403 g10/import.c:601
#, c-format
msgid "key %08lX: can't read original keyblock: %s\n"
-msgstr "Schlüssel %08lX: Lesefehler im lokalen originalen Schlüsselblocks: %s\n"
+msgstr ""
+"Schlüssel %08lX: Lesefehler im lokalen originalen Schlüsselblocks: %s\n"
#: g10/import.c:420 g10/import.c:532 g10/import.c:636
msgid "writing keyblock\n"
msgstr "Schreiben des Schlüsselblocks\n"
#: g10/import.c:426 g10/import.c:642
#, c-format
msgid "can't write keyblock: %s\n"
msgstr "Der Schlüsselblock kann nicht geschrieben werden: %s\n"
#: g10/import.c:431
#, c-format
msgid "key %08lX: 1 new user-id\n"
msgstr "Schlüssel %08lX: 1 neue User-ID\n"
#: g10/import.c:434
#, c-format
msgid "key %08lX: %d new user-ids\n"
msgstr "Schlüssel %08lX: %d neue User-IDs\n"
#: g10/import.c:437
#, c-format
msgid "key %08lX: 1 new signature\n"
msgstr "Schlüssel %08lX: 1 neue Signatur\n"
#: g10/import.c:440
#, c-format
msgid "key %08lX: %d new signatures\n"
msgstr "Schlüssel %08lX: %d neue Signaturen\n"
#: g10/import.c:443
#, c-format
msgid "key %08lX: 1 new subkey\n"
msgstr "Schlüssel %08lX: 1 neuer Unterschlüssel\n"
#: g10/import.c:446
#, c-format
msgid "key %08lX: %d new subkeys\n"
msgstr "Schlüssel %08lX: %d neue Unterschlüssel\n"
#: g10/import.c:456
#, c-format
msgid "key %08lX: not changed\n"
msgstr "Schlüssel %08lX: Nicht geändert\n"
#: g10/import.c:535
#, c-format
msgid "can't lock secret keyring: %s\n"
msgstr "kann geheimen Schlüsselbund nicht sperren: %s\n"
#: g10/import.c:538
#, c-format
msgid "can't write keyring: %s\n"
msgstr "kann Schlüsselbund nicht schreiben: %s\n"
#. we are ready
#: g10/import.c:541
#, c-format
msgid "key %08lX: secret key imported\n"
msgstr "Schlüssel %08lX: Geheimer Schlüssel importiert\n"
#. we can't merge secret keys
#: g10/import.c:545
#, c-format
msgid "key %08lX: already in secret keyring\n"
msgstr "Schlüssel %08lX: Ist bereits im geheimen Schlüsselbund\n"
#: g10/import.c:550
#, c-format
msgid "key %08lX: secret key not found: %s\n"
msgstr "Schlüssel %08lX: geheimer Schlüssel nicht gefunden: %s\n"
#: g10/import.c:579
#, c-format
msgid "key %08lX: no public key - can't apply revocation certificate\n"
msgstr ""
"Schlüssel %08lX: Kein öffentlicher Schlüssel - der Schlüsselwiderruf kann "
"nicht angebracht werden\n"
#: g10/import.c:612
#, c-format
msgid "key %08lX: invalid revocation certificate: %s - rejected\n"
msgstr "Schlüssel %08lX: Ungültiges Widerrufzertifikat: %s - zurückgewiesen\n"
#: g10/import.c:646
#, c-format
msgid "key %08lX: revocation certificate imported\n"
msgstr "Schlüssel %08lX: Widerrufzertifikat importiert\n"
#: g10/import.c:677
#, c-format
msgid "key %08lX: no user-id for signature\n"
msgstr "Schlüssel %08lX: Keine User-ID für Signatur\n"
#: g10/import.c:684
#, c-format
msgid "key %08lX: unsupported public key algorithm\n"
msgstr "Schlüssel %08lX: Nicht unterstützetes Public-Key-Verfahren\n"
#: g10/import.c:685
#, c-format
msgid "key %08lX: invalid self-signature\n"
msgstr "Schlüssel %08lX: Ungültige Eigenbeglaubigung\n"
#: g10/import.c:714
#, c-format
msgid "key %08lX: skipped userid '"
msgstr "Schlüssel %08lX: übergehe User-ID '"
#: g10/import.c:737
#, c-format
msgid "key %08lX: revocation certificate at wrong place - skipped\n"
msgstr "Schlüssel %08lX: Widerrufzertifikat an falschem Platz - übergangen\n"
#: g10/import.c:745
#, c-format
msgid "key %08lX: invalid revocation certificate: %s - skipped\n"
msgstr "Schlüssel %08lX: Ungültiges Widerrufzertifikat: %s - übergangen\n"
#: g10/import.c:804
#, c-format
msgid "key %08lX: revocation certificate added\n"
msgstr "Schlüssel %08lX: Widerrufzertifikat hinzugefügt\n"
#: g10/import.c:918 g10/import.c:973
#, c-format
msgid "key %08lX: our copy has no self-signature\n"
msgstr "Schlüssel %08lX: Unsere Kopie hat keine Eigenbeglaubigung\n"
#: g10/keyedit.c:81
#, c-format
msgid "%s: user not found\n"
msgstr "%s: Benutzer nicht gefunden\n"
#: g10/keyedit.c:164
msgid "[self-signature]"
msgstr "[Eigenbeglaubigung]"
#: g10/keyedit.c:182
msgid "1 bad signature\n"
msgstr "%d schlechte Signaturen\n"
#: g10/keyedit.c:184
#, c-format
msgid "%d bad signatures\n"
msgstr "%d falsche Beglaubigungen\n"
#: g10/keyedit.c:186
msgid "1 signature not checked due to a missing key\n"
msgstr "1 Beglaubigung wegen fehlendem Schlüssel nicht geprüft\n"
#: g10/keyedit.c:188
#, c-format
msgid "%d signatures not checked due to missing keys\n"
msgstr "%d Beglaubigungen wegen fehlenden Schlüsseln nicht geprüft\n"
#: g10/keyedit.c:190
msgid "1 signature not checked due to an error\n"
msgstr "1 Beglaubigung aufgrund von Fehler nicht geprüft\n"
#: g10/keyedit.c:192
#, c-format
msgid "%d signatures not checked due to errors\n"
msgstr "%d Beglaubigungen aufgrund von Fehlern nicht geprüft\n"
#: g10/keyedit.c:194
msgid "1 user id without valid self-signature detected\n"
msgstr "Eine User-ID ohne gültige Eigenbeglaubigung entdeckt\n"
#: g10/keyedit.c:196
#, c-format
msgid "%d user ids without valid self-signatures detected\n"
msgstr "%d User-IDs ohne gültige Eigenbeglaubigung entdeckt\n"
#: g10/keyedit.c:258
#, c-format
msgid "Already signed by key %08lX\n"
msgstr "Ist bereits durch Schlüssel %08lX beglaubigt.\n"
#: g10/keyedit.c:266
#, c-format
msgid "Nothing to sign with key %08lX\n"
msgstr "Nichts zu beglaubigen für Schlüssel %08lX\n"
#: g10/keyedit.c:275
msgid ""
"Are you really sure that you want to sign this key\n"
"with your key: \""
msgstr ""
"Sind Sie wirklich sicher, daß Sie diesen Schlüssel mit Ihrem\n"
"Schlüssel beglaubigen wollen: \""
#: g10/keyedit.c:282
msgid "Really sign? "
msgstr "Wurklich unterschreiben? "
#: g10/keyedit.c:303 g10/sign.c:65
#, c-format
msgid "signing failed: %s\n"
msgstr "BEglaubigung fehlgeschlagen: %s\n"
#: g10/keyedit.c:356
msgid "This key is not protected.\n"
msgstr "Dieser Schlüssel ist nicht geschützt.\n"
#: g10/keyedit.c:359
msgid "Key is protected.\n"
msgstr "Schlüssel ist geschützt.\n"
#: g10/keyedit.c:376
#, c-format
msgid "Can't edit this key: %s\n"
msgstr "Dieser Schlüssel kann nicht editiert werden: %s\n"
#: g10/keyedit.c:381
msgid ""
"Enter the new passphrase for this secret key.\n"
"\n"
msgstr ""
"Geben Sie das neue Mantra für diesen geheimen Schlüssel ein.\n"
"\n"
#: g10/keyedit.c:393
msgid ""
"You don't want a passphrase - this is probably a *bad* idea!\n"
"\n"
msgstr ""
"Sie wollen kein Mantra - dies ist bestimmt *keine* gute Idee!\n"
"\n"
#: g10/keyedit.c:396
msgid "Do you really want to do this? "
msgstr "Möchten Sie dies wirklich tun? "
#: g10/keyedit.c:455
msgid "moving a key signature to the correct place\n"
msgstr "schiebe eine Beglaubigung an die richtige Stelle\n"
#: g10/keyedit.c:490
msgid "quit"
msgstr "quit"
#: g10/keyedit.c:490
msgid "quit this menu"
msgstr "Menü verlassen"
#: g10/keyedit.c:491
msgid "q"
msgstr "q"
#: g10/keyedit.c:492
msgid "save"
msgstr "save"
#: g10/keyedit.c:492
msgid "save and quit"
msgstr "speichern und Menü verlassen"
#: g10/keyedit.c:493
msgid "help"
msgstr "help"
#: g10/keyedit.c:493
msgid "show this help"
msgstr "Diese Hilfe zeigen"
#: g10/keyedit.c:495
msgid "fpr"
msgstr "fpr"
#: g10/keyedit.c:495
msgid "show fingerprint"
msgstr "\"Fingerabdruck\" anzeigen"
#: g10/keyedit.c:496
msgid "list"
msgstr "Liste der Schlüssel"
#: g10/keyedit.c:496
msgid "list key and user ids"
msgstr "Schlüssel und User-ID auflisten"
#: g10/keyedit.c:497
msgid "l"
msgstr "l"
#: g10/keyedit.c:498
msgid "uid"
msgstr "uid"
#: g10/keyedit.c:498
msgid "select user id N"
msgstr "User-ID N auswählen"
#: g10/keyedit.c:499
msgid "key"
msgstr "key"
#: g10/keyedit.c:499
msgid "select secondary key N"
msgstr "Zweitschlüssel N auswählen"
#: g10/keyedit.c:500
msgid "check"
msgstr "check"
#: g10/keyedit.c:500
msgid "list signatures"
msgstr "Liste der Signaturen"
#: g10/keyedit.c:501
msgid "c"
msgstr "c"
#: g10/keyedit.c:502
msgid "sign"
msgstr "sign"
#: g10/keyedit.c:502
msgid "sign the key"
msgstr "Den Schlüssel signieren"
#: g10/keyedit.c:503
msgid "s"
msgstr "s"
#: g10/keyedit.c:504
msgid "debug"
msgstr "debug"
#: g10/keyedit.c:505
msgid "adduid"
msgstr "adduid"
#: g10/keyedit.c:505
msgid "add a user id"
msgstr "Eine User-ID hinzufügen"
#: g10/keyedit.c:506
msgid "deluid"
msgstr "deluid"
#: g10/keyedit.c:506
msgid "delete user id"
msgstr "User-ID entfernen"
#: g10/keyedit.c:507
msgid "addkey"
msgstr "addkey"
#: g10/keyedit.c:507
msgid "add a secondary key"
msgstr "Einen Zweitschlüssel hinzufügen"
#: g10/keyedit.c:508
msgid "delkey"
msgstr "delkey"
#: g10/keyedit.c:508
msgid "delete a secondary key"
msgstr "Einen Zweitschlüssel entfernen"
#: g10/keyedit.c:509
msgid "expire"
msgstr "expire"
#: g10/keyedit.c:509
msgid "change the expire date"
msgstr "Ändern des Verfallsdatums"
#: g10/keyedit.c:510
msgid "toggle"
msgstr "toggle"
#: g10/keyedit.c:510
msgid "toggle between secret and public key listing"
msgstr "Umschalten zwischen Anzeige geheimer und öffentlicher Schlüssel"
#: g10/keyedit.c:512
msgid "t"
msgstr "t"
#: g10/keyedit.c:513
msgid "pref"
msgstr "pref"
#: g10/keyedit.c:513
msgid "list preferences"
msgstr "Liste der Voreinstellungen"
#: g10/keyedit.c:514
msgid "passwd"
msgstr "passwd"
#: g10/keyedit.c:514
msgid "change the passphrase"
msgstr "Das Mantra ändern"
#: g10/keyedit.c:515
msgid "trust"
msgstr "trust"
#: g10/keyedit.c:515
msgid "change the ownertrust"
msgstr "Den \"Owner trust\" ändern"
#: g10/keyedit.c:534
msgid "can't do that in batchmode\n"
msgstr "Dies kann im Batchmodus nicht durchgeführt werden.\n"
#. check that they match
#. FIXME: check that they both match
#: g10/keyedit.c:561
msgid "Secret key is available.\n"
msgstr "Geheimer Schlüssel ist vorhanden.\n"
#: g10/keyedit.c:590
msgid "Command> "
msgstr "Befehl> "
#: g10/keyedit.c:617
msgid "Need the secret key to do this.\n"
msgstr "Hierzu wird der geheime Schlüssel benötigt.\n"
#: g10/keyedit.c:639
msgid "Save changes? "
msgstr "Änderungen speichern? "
#: g10/keyedit.c:642
msgid "Quit without saving? "
msgstr "Beenden ohne zu speichern? "
#: g10/keyedit.c:652
#, c-format
msgid "update failed: %s\n"
msgstr "Änderung fehlgeschlagen: %s\n"
#: g10/keyedit.c:659
#, c-format
msgid "update secret failed: %s\n"
msgstr "Änderung des Geheimnisses fehlgeschlagen: %s\n"
#: g10/keyedit.c:666
msgid "Key not changed so no update needed.\n"
msgstr "Schlüssel ist nicht geändert worden, also ist keine Änderung nötig.\n"
#: g10/keyedit.c:669 g10/keyedit.c:727
#, c-format
msgid "update of trust db failed: %s\n"
msgstr "Änderung der \"Trust-DB\" fehlgeschlagen: %s\n"
#: g10/keyedit.c:701
msgid "Really sign all user ids? "
msgstr "Wirklich alle User-IDs beglaubigen? "
#: g10/keyedit.c:702
msgid "Hint: Select the user ids to sign\n"
msgstr "Tip: Wählen Sie die User-ID, die beglaubigt werden soll\n"
#: g10/keyedit.c:738
msgid "You must select at least one user id.\n"
msgstr "Zumindestens eine User-ID muß ausgewählt werden.\n"
#: g10/keyedit.c:740
msgid "You can't delete the last user id!\n"
msgstr "Die letzte User-ID kann nicht gelöscht werden!\n"
#: g10/keyedit.c:743
msgid "Really remove all selected user ids? "
msgstr "Möchten Sie alle ausgewählten User-IDs wirklich entfernen? "
#: g10/keyedit.c:744
msgid "Really remove this user id? "
msgstr "Diese User-ID wirklich entfernen? "
#: g10/keyedit.c:767
msgid "You must select at least one key.\n"
msgstr "Zumindestens ein Schlüssel muß ausgewählt werden.\n"
#: g10/keyedit.c:771
msgid "Do you really want to delete the selected keys? "
msgstr "Möchten Sie die ausgewählten Schlüssel wirklich entfernen? "
#: g10/keyedit.c:772
msgid "Do you really want to delete this key? "
msgstr "Möchten Sie diesen Schlüssel wirklich entfernen? "
#: g10/keyedit.c:819
msgid "Invalid command (try \"help\")\n"
msgstr "Ungültiger Befehl (versuchen Sie's mal mit \"help\")\n"
#: g10/keyedit.c:1197
msgid "Please remove selections from the secret keys.\n"
msgstr "Bitte entfernen Sie die Auswahl von den geheimen Schlüsseln.\n"
#: g10/keyedit.c:1203
msgid "Please select at most one secondary key.\n"
msgstr "Bitte wählen Sie höchstens einen Zweitschlüssel aus.\n"
#: g10/keyedit.c:1207
msgid "Changing exiration time for a secondary key.\n"
msgstr "Ändern des Verfallsdatums des Zweitschlüssels.\n"
#: g10/keyedit.c:1209
msgid "Changing exiration time for the primary key.\n"
msgstr "Ändern des Verfallsdatums des Hauptschlüssels.\n"
#: g10/keyedit.c:1250
msgid "You can't change the expiration date of a v3 key\n"
msgstr "Sie können das Verfallsdatum eines v3-Schlüssels nicht ändern\n"
#: g10/keyedit.c:1266
msgid "No corresponding signature in secret ring\n"
msgstr "Keine entsprechende Signatur im geheimen Schlüsselbund\n"
#: g10/keyedit.c:1326
#, c-format
msgid "No user id with index %d\n"
msgstr "Keine User-ID mit Index %d\n"
#: g10/keyedit.c:1371
#, c-format
msgid "No secondary key with index %d\n"
msgstr "Kein Zweitschlüssel mit Index %d\n"
#: g10/mainproc.c:198
msgid "public key encrypted data: Good DEK\n"
msgstr "Mit öffentlichem Schüssel verschlüsselte Daten: Korrekte DEK\n"
#: g10/mainproc.c:201
#, c-format
msgid "public key decryption failed: %s\n"
msgstr "Entschlüsselung mit öffentlichem Schlüssel fehlgeschlagen: %s\n"
#: g10/mainproc.c:228
msgid "decryption okay\n"
msgstr "Enschlüsselung fehlgeschlagen: %s\n"
#: g10/mainproc.c:231
#, c-format
msgid "decryption failed: %s\n"
msgstr "Enschlüsselung fehlgeschlagen: %s\n"
#: g10/mainproc.c:248
msgid "NOTE: sender requested \"for-your-eyes-only\"\n"
msgstr ""
"Hinweis: Der Absender verlangte Vertraulichkeit(\"for-your-eyes-only\")\n"
#: g10/mainproc.c:250
#, c-format
msgid "original file name='%.*s'\n"
msgstr "Ursprünglicher Dateiname='%.*s'\n"
#: g10/mainproc.c:833
msgid "signature verification suppressed\n"
msgstr "Unterschriften-Überprüfung unterdrückt\n"
#: g10/mainproc.c:839
#, c-format
msgid "Signature made %.*s using %s key ID %08lX\n"
msgstr "Unterschrieben am %.*s mit %s Schlüssel %08lX\n"
#: g10/mainproc.c:847
msgid "BAD signature from \""
msgstr "FALSCHE Unterschrift von \""
#: g10/mainproc.c:848
msgid "Good signature from \""
msgstr "Korrekte Unterschrift von \""
#: g10/mainproc.c:861
#, c-format
msgid "Can't check signature: %s\n"
msgstr "Signatur kann nicht geprüft werden: %s\n"
#: g10/mainproc.c:934
msgid "old style (PGP 2.x) signature\n"
msgstr "Unterschrift nach alter (PGP 2.x) Art\n"
#: g10/mainproc.c:939
msgid "invalid root packet detected in proc_tree()\n"
msgstr "ungültiges root-Paket in proc_tree() entdeckt\n"
#: g10/misc.c:88
#, c-format
msgid "can't disable core dumps: %s\n"
msgstr "core-dump-Erzeugung kann nicht abgeschaltet werden: %s\n"
#: g10/misc.c:90
msgid "WARNING: Program may create a core file!\n"
msgstr "WARNUNG: Programm könnte einen core-dump schreiben!\n"
+#: g10/misc.c:198
+msgid "Experimental algorithms should not be used!\n"
+msgstr ""
+
+#: g10/misc.c:212
+msgid ""
+"RSA keys are deprecated; please consider creating a new key and use this key "
+"in the future\n"
+msgstr ""
+"RSA Schlüssel sind nicht erwünscht; bitte denken Sie darüber nach, einen\n"
+"neuen Schlüssel zu erzeugen und diesen in Zukunft zu benutzen\n"
+
+#: g10/misc.c:233
+msgid "This cipher algorithm is depreciated; please use a more standard one!\n"
+msgstr ""
+
#: g10/parse-packet.c:109
#, c-format
msgid "can't handle public key algorithm %d\n"
msgstr "dieses Public-Key Verfahren %d kann nicht benutzt werden\n"
+#: g10/parse-packet.c:801
+#, c-format
+msgid "subpacket of type %d has critical bit set\n"
+msgstr ""
+
#: g10/passphrase.c:141
msgid ""
"\n"
"You need a passphrase to unlock the secret key for\n"
"user: \""
msgstr ""
"\n"
"Sie benötigen ein Mantra, um den geheimen Schlüssel zu entsperren.\n"
"Benutzer: \""
#: g10/passphrase.c:150
#, c-format
msgid "(%u-bit %s key, ID %08lX, created %s)\n"
msgstr "(%u-Bit %s Schlüssel, ID %08lX, erzeugt %s)\n"
#: g10/passphrase.c:174
msgid "Enter passphrase: "
msgstr "Geben Sie das Mantra ein: "
#: g10/passphrase.c:178
msgid "Repeat passphrase: "
msgstr "Geben Sie das Mantra nochmal ein: "
-#: g10/plaintext.c:102
+#: g10/plaintext.c:103
msgid "data not saved; use option \"--output\" to save it\n"
msgstr ""
"Daten wurden nicht gespeichert; verwenden Sie dafür die Option \"--output\"\n"
-#: g10/plaintext.c:215
+#: g10/plaintext.c:216
msgid "Please enter name of data file: "
msgstr "Bitte geben Sie den Namen der Datendatei ein: "
-#: g10/plaintext.c:236
+#: g10/plaintext.c:237
msgid "reading stdin ...\n"
msgstr "lese stdin ...\n"
-#: g10/plaintext.c:299
+#: g10/plaintext.c:300
#, c-format
msgid "can't open signed data '%s'\n"
msgstr "kann signierte Datei '%s' nicht öffnen.\n"
#: g10/pubkey-enc.c:78
#, c-format
msgid "anonymous receiver; trying secret key %08lX ...\n"
msgstr "Ungenannter Empfänger: Versuch mit geheimen Schlüssel %08lX ...\n"
#: g10/pubkey-enc.c:84
msgid "okay, we are the anonymous receiver.\n"
msgstr "Alles klar, wir sind der ungenannte Empfänger.\n"
#: g10/pubkey-enc.c:136
msgid "old encoding of the DEK is not supported\n"
msgstr "alte Kodierung des DEK wird nicht unterstützt\n"
#: g10/pubkey-enc.c:183
#, c-format
msgid "NOTE: cipher algorithm %d not found in preferences\n"
msgstr "Hinweis: Verfahren %d ist kein bevorzugtes Verschlüsselungsverfahren\n"
#: g10/seckey-cert.c:56
#, c-format
msgid "protection algorithm %d is not supported\n"
msgstr "Schutzverfahren %d wird nicht unterstützt\n"
#: g10/seckey-cert.c:169
msgid "Invalid passphrase; please try again ...\n"
msgstr "Ungültiges Mantra; versuchen Sie's doch noch einmal ...\n"
-#: g10/seckey-cert.c:215
+#: g10/seckey-cert.c:216
msgid "WARNING: Weak key detected - please change passphrase again.\n"
msgstr ""
"WARNUNG: Unsicherer Schlüssel entdeckt -\n"
" bitte das Mantra nochmal eingeben.\n"
#: g10/sig-check.c:155
msgid ""
"this is a PGP generated ElGamal key which is NOT secure for signatures!\n"
msgstr ""
"Dieser durch PGP erzeugte ElGamal-Schlüssel ist für Signaturen NICHT sicher "
"genug!\n"
#: g10/sig-check.c:165
msgid "public key created in future (time warp or clock problem)\n"
msgstr ""
"Öffentlicher Schlüssel wurde in der Zukunft erzeugt (Zeitreise oder Uhren "
"stimmen nicht überein)\n"
#: g10/sig-check.c:170
#, c-format
msgid "NOTE: signature key expired %s\n"
msgstr "Hinweis: Schlüssel der Signatur ist verfallen am %s.\n"
+#: g10/sig-check.c:226
+msgid "assuming bad signature due to an unknown critical bit\n"
+msgstr ""
+
#: g10/sign.c:69
#, c-format
msgid "%s signature from: %s\n"
msgstr "%s Unterschrift von: %s\n"
-#: g10/sign.c:200 g10/sign.c:558
+#: g10/sign.c:200 g10/sign.c:587
#, c-format
msgid "can't create %s: %s\n"
msgstr "%s kann nicht erzeugt werden: %s\n"
#: g10/sign.c:296
msgid "signing:"
msgstr "unterschreibe:"
#: g10/sign.c:336
#, c-format
msgid "WARNING: '%s' is an empty file\n"
msgstr "WARNUNG: '%s' ist eine leere Datei.\n"
#: g10/tdbio.c:116 g10/tdbio.c:1413
#, c-format
msgid "trustdb rec %lu: lseek failed: %s\n"
msgstr "trustdb Satz %lu: lseek fehlgeschlagen: %s\n"
#: g10/tdbio.c:122 g10/tdbio.c:1420
#, c-format
msgid "trustdb rec %lu: write failed (n=%d): %s\n"
msgstr "trustdb Satz %lu: write fehlgeschlagen (n=%d): %s\n"
#: g10/tdbio.c:232
msgid "trustdb transaction to large\n"
msgstr "trustdb Transaktion zu groß\n"
#: g10/tdbio.c:402
#, c-format
msgid "%s: can't access: %s\n"
msgstr "%s: kann nicht zugegriffen werden: %s\n"
#: g10/ringedit.c:273 g10/tdbio.c:422
#, c-format
msgid "%s: can't create directory: %s\n"
msgstr "%s: Verzeichnis kann nicht erzeugt werden: %s\n"
#: g10/ringedit.c:279 g10/tdbio.c:425
#, c-format
msgid "%s: directory created\n"
msgstr "%s: Verzeichnis erzeugt\n"
#: g10/tdbio.c:429
#, c-format
msgid "%s: directory does not exist!\n"
msgstr "%s: Verzeichnis existiert nicht!\n"
#: g10/openfile.c:101 g10/openfile.c:165 g10/ringedit.c:1256 g10/tdbio.c:435
#, c-format
msgid "%s: can't create: %s\n"
msgstr "%s: kann nicht erzeugt werden: %s\n"
#: g10/tdbio.c:459
#, c-format
msgid "%s: failed to create version record: %s"
msgstr "%s: Fehler beim Erzeugen des Versionsatzes: %s"
#: g10/tdbio.c:463
#, c-format
msgid "%s: invalid trust-db created\n"
msgstr "%s: ungültige trust-db erzeugt\n"
#: g10/tdbio.c:465
#, c-format
msgid "%s: trust-db created\n"
msgstr "%s: trust-db erzeugt\n"
#: g10/tdbio.c:506
#, c-format
msgid "%s: invalid trust-db\n"
msgstr "%s: ungülte 'Trust'-Datenbank\n"
#: g10/tdbio.c:540
#, c-format
msgid "%s: failed to create hashtable: %s\n"
msgstr "%s: hashtable kann nicht erzeugt werden: %s\n"
#: g10/tdbio.c:548
#, c-format
msgid "%s: error updating version record: %s\n"
msgstr "%s: Fehler beim Ändern des Versionsatzes: %s\n"
#: g10/tdbio.c:564 g10/tdbio.c:603 g10/tdbio.c:628 g10/tdbio.c:1346
#: g10/tdbio.c:1373
#, c-format
msgid "%s: error reading version record: %s\n"
msgstr "%s: Fehler beim Lesen des Versionsatzes: %s\n"
#: g10/tdbio.c:577
#, c-format
msgid "%s: error writing version record: %s\n"
msgstr "%s: Fehler beim Schreiben des Versionsatzes: %s\n"
#: g10/tdbio.c:1053
#, c-format
msgid "trustdb: lseek failed: %s\n"
msgstr "trustdb: lseek fehlgeschlagen: %s\n"
#: g10/tdbio.c:1061
#, c-format
msgid "trustdb: read failed (n=%d): %s\n"
msgstr "trustdb: read failed (n=%d): %s\n"
#: g10/tdbio.c:1082
#, c-format
msgid "%s: not a trustdb file\n"
msgstr "%s: keine trustdb Datei\n"
#: g10/tdbio.c:1098
#, c-format
msgid "%s: version record with recnum %lu\n"
msgstr "%s: version record with recnum %lu\n"
#: g10/tdbio.c:1103
#, c-format
msgid "%s: invalid file version %d\n"
msgstr "%s: invalid file version %d\n"
#: g10/tdbio.c:1379
#, c-format
msgid "%s: error reading free record: %s\n"
msgstr "%s: Fehler beim Lesen eines freien Satzes: %s\n"
#: g10/tdbio.c:1387
#, c-format
msgid "%s: error writing dir record: %s\n"
msgstr "%s: Fehler beim Schreiben eines Verzeichnis-Satzes: %s\n"
#: g10/tdbio.c:1397
#, c-format
msgid "%s: failed to zero a record: %s\n"
msgstr "%s: konnte einen Satz nicht Nullen: %s\n"
#: g10/tdbio.c:1427
#, c-format
msgid "%s: failed to append a record: %s\n"
msgstr "%s: konnte Satz nicht anhängen: %s\n"
-#: g10/trustdb.c:134
+#: g10/trustdb.c:142
msgid "The trust DB is corrupted; please run \"gpgm --fix-trust-db\".\n"
msgstr ""
"Die \"Trust\"-Datenbank ist beschädigt; verwenden Sie \"gpgm "
"--fix-trustdb\".\n"
-#: g10/trustdb.c:147
+#: g10/trustdb.c:155
#, c-format
msgid "trust record %lu, req type %d: read failed: %s\n"
msgstr "trust record %lu, req type %d: read failed: %s\n"
-#: g10/trustdb.c:162
+#: g10/trustdb.c:170
#, c-format
msgid "trust record %lu, type %d: write failed: %s\n"
msgstr "trust record %lu, type %d: write failed: %s\n"
-#: g10/trustdb.c:176
+#: g10/trustdb.c:184
#, c-format
msgid "trust record %lu: delete failed: %s\n"
msgstr "Vertrauenssatz %lu: löschen fehlgeschlagen: %s\n"
-#: g10/trustdb.c:190
+#: g10/trustdb.c:198
#, c-format
msgid "trust db: sync failed: %s\n"
msgstr "\"Trust-DB\": sync fehlgeschlagen: %s\n"
-#: g10/trustdb.c:319
+#: g10/trustdb.c:327
#, c-format
msgid "error reading dir record for LID %lu: %s\n"
msgstr "Fehler beim Lesen des Dir-Satzes für LID %lu: %s\n"
-#: g10/trustdb.c:326
+#: g10/trustdb.c:334
#, c-format
msgid "lid %lu: expected dir record, got type %d\n"
msgstr "lid %lu: Dir-Satz erwartet, aber es kam Typ %d\n"
-#: g10/trustdb.c:331
+#: g10/trustdb.c:339
#, c-format
msgid "no primary key for LID %lu\n"
msgstr "Kein Hauptschlüssel für LID %lu\n"
-#: g10/trustdb.c:336
+#: g10/trustdb.c:344
#, c-format
msgid "error reading primary key for LID %lu: %s\n"
msgstr "Fehler beim Lesen den Hauptschlüssels der LID %lu: %s\n"
-#: g10/trustdb.c:412
+#: g10/trustdb.c:420
#, c-format
msgid "chained sigrec %lu has a wrong owner\n"
msgstr "Verketteter Signatursatz %lu hat einen falschen Besitzer\n"
-#: g10/trustdb.c:455
+#: g10/trustdb.c:463
#, c-format
msgid "'%s' is not a valid long keyID\n"
msgstr "'%s' ist keine gültige lange Schlüssel-ID\n"
-#: g10/trustdb.c:490
+#: g10/trustdb.c:498
#, c-format
msgid "key %08lX: no public key for trusted key - skipped\n"
-msgstr "Schlüssel %08lX: kein öffentlicher Schüssel für vertrauenswürdigen Schlüssel - übersprungen\n"
+msgstr ""
+"Schlüssel %08lX: kein öffentlicher Schüssel für vertrauenswürdigen Schlüssel "
+"- übersprungen\n"
-#: g10/trustdb.c:499 g10/trustdb.c:557
+#: g10/trustdb.c:507 g10/trustdb.c:565
#, c-format
msgid "key %08lX: can't put it into the trustdb\n"
msgstr "Schlüssel %08lX kann nicht in die \"trustdb\" eingefügt werden\n"
-#: g10/trustdb.c:504 g10/trustdb.c:563
+#: g10/trustdb.c:512 g10/trustdb.c:571
#, c-format
msgid "key %08lX: query record failed\n"
msgstr "Schlüssel %08lX: Satzabfrage fehlgeschlagen\n"
-#: g10/trustdb.c:509 g10/trustdb.c:572
+#: g10/trustdb.c:517 g10/trustdb.c:580
#, c-format
msgid "key %08lX: already in trusted key table\n"
msgstr "Schlüssel %08lX: Ist bereits in geheimer Schlüsseltabelle\n"
-#: g10/trustdb.c:512 g10/trustdb.c:575
+#: g10/trustdb.c:520 g10/trustdb.c:583
#, c-format
msgid "key %08lX: accepted as trusted key.\n"
msgstr "Schlüssel %08lX: Akzeptiert als vertrauenswürdiger Schlüssel.\n"
-#: g10/trustdb.c:528
+#: g10/trustdb.c:536
#, c-format
msgid "NOTE: secret key %08lX is NOT protected.\n"
msgstr "HINWEIS: Geheimer Schlüssel %08lX ist NICHT geschützt.\n"
-#: g10/trustdb.c:540
+#: g10/trustdb.c:548
#, c-format
msgid "key %08lX: secret key without public key - skipped\n"
-msgstr "Schlüssel %08lX: geheimer Schlüssel, aber ohne öffentlichen Schlüssel - übersprungen\n"
+msgstr ""
+"Schlüssel %08lX: geheimer Schlüssel, aber ohne öffentlichen Schlüssel - "
+"übersprungen\n"
-#: g10/trustdb.c:547
+#: g10/trustdb.c:555
#, c-format
msgid "key %08lX: secret and public key don't match\n"
msgstr ""
"Schlüssel %08lX: geheimer und öffentlicher Schlüssel passen nicht zusammen.\n"
-#: g10/trustdb.c:583
+#: g10/trustdb.c:591
#, c-format
msgid "enumerate secret keys failed: %s\n"
msgstr "enum_secret_keys fehlgeschlagen: %s\n"
-#: g10/trustdb.c:766
+#: g10/trustdb.c:774
#, c-format
msgid "lid %lu: read dir record failed: %s\n"
msgstr "lid %lu: Lesen des Verz.Satzes fehlgeschlagen: %s\n"
-#: g10/trustdb.c:775
+#: g10/trustdb.c:783
#, c-format
msgid "lid %lu: read key record failed: %s\n"
msgstr "lid %lu: Lesen des Schl..Satzes fehlgeschlagen: %s\n"
-#: g10/trustdb.c:785
+#: g10/trustdb.c:793
#, c-format
msgid "lid %lu: read uid record failed: %s\n"
msgstr "lid %lu: Lesen des UserID-Satzes fehlgeschlagen: %s\n"
-#: g10/trustdb.c:794
+#: g10/trustdb.c:802
#, c-format
msgid "lid %lu: read pref record failed: %s\n"
msgstr "lid %lu: Lesen des Pref.Satzes fehlgeschlagen: %s\n"
-#: g10/trustdb.c:804
+#: g10/trustdb.c:812
#, c-format
msgid "lid %lu: read sig record failed: %s\n"
msgstr "lid %lu: Lesen des Sig.Satzes fehlgeschlagen: %s\n"
-#: g10/trustdb.c:999
+#: g10/trustdb.c:1013
msgid "Ooops, no keys\n"
msgstr "Huch, keine Schlüssel\n"
-#: g10/trustdb.c:1003
+#: g10/trustdb.c:1017
msgid "Ooops, no user ids\n"
msgstr "Huch, keine User-IDs\n"
-#: g10/trustdb.c:1074 g10/trustdb.c:1092
+#: g10/trustdb.c:1088 g10/trustdb.c:1106
#, c-format
msgid "user '%s' read problem: %s\n"
msgstr "User '%s' Leseproblem: %s\n"
-#: g10/trustdb.c:1077 g10/trustdb.c:1095
+#: g10/trustdb.c:1091 g10/trustdb.c:1109
#, c-format
msgid "user '%s' list problem: %s\n"
msgstr "User '%s' Listenproblem: %s\n"
-#: g10/trustdb.c:1085 g10/trustdb.c:1300
+#: g10/trustdb.c:1099 g10/trustdb.c:1346
#, c-format
msgid "user '%s' not found: %s\n"
msgstr "Benutzer '%s' nicht gefunden: %s\n"
-#: g10/trustdb.c:1087 g10/trustdb.c:1302
+#: g10/trustdb.c:1101 g10/trustdb.c:1348
#, c-format
msgid "problem finding '%s' in trustdb: %s\n"
msgstr "Problem, '%s' in der Trust-DB zu finden: %s\n"
-#: g10/trustdb.c:1090
+#: g10/trustdb.c:1104
#, c-format
msgid "user '%s' not in trustdb\n"
msgstr "User '%s' ist nicht in der trustdb\n"
-#: g10/trustdb.c:1125
+#: g10/trustdb.c:1139
#, c-format
msgid ""
"# List of assigned trustvalues, created %s\n"
"# (Use \"gpgm --import-ownertrust\" to restore them)\n"
msgstr ""
"# Liste der zugewisenen \"trustvalues\", erzeugt am %s\n"
"# (Verwenden Sie \"gpgm --import-ownertrust\" um sie wieder einzuspielen)\n"
-#: g10/trustdb.c:1131
+#: g10/trustdb.c:1145
msgid "directory record w/o primary key\n"
msgstr "Verzeichnis-Satz ohne Hauptschlüssel\n"
-#: g10/trustdb.c:1138
+#: g10/trustdb.c:1152
#, c-format
msgid "error reading key record: %s\n"
msgstr "Fehler beim Lesen des Schl.Satzes: %s\n"
-#: g10/trustdb.c:1178
+#: g10/trustdb.c:1192
msgid "line too long\n"
msgstr "Zeile zu lang\n"
-#: g10/trustdb.c:1186
+#: g10/trustdb.c:1200
msgid "error: missing colon\n"
msgstr "Fehler: Fehlender Doppelpunkt\n"
-#: g10/trustdb.c:1191
+#: g10/trustdb.c:1205
msgid "error: invalid fingerprint\n"
msgstr "Fehler: ungültiger Fingerabdruck\n"
-#: g10/trustdb.c:1195
+#: g10/trustdb.c:1209
msgid "error: no ownertrust value\n"
msgstr "Fehler: Keine \"Owner trust\" Werte\n"
-#: g10/trustdb.c:1209
+#: g10/trustdb.c:1223
#, c-format
msgid "LID %lu: changing trust from %u to %u\n"
msgstr "LID %lu: Ändern des 'Trusts' von %u auf %u\n"
-#: g10/trustdb.c:1212
+#: g10/trustdb.c:1226
#, c-format
msgid "LID %lu: setting trust to %u\n"
msgstr "LID %lu: Setze 'Trust' auf %u\n"
-#: g10/trustdb.c:1220
+#: g10/trustdb.c:1234
msgid "key not in trustdb, searching ring.\n"
msgstr "Schlüssel ist nicht in der trustdb, Schl.bund wird durchsucht.\n"
-#: g10/trustdb.c:1223
+#: g10/trustdb.c:1237
#, c-format
msgid "key not in ring: %s\n"
msgstr "Schlüssel ist nicht im Schlüsselbund: %s\n"
-#: g10/trustdb.c:1227
+#: g10/trustdb.c:1241
msgid "Oops: key is now in trustdb???\n"
msgstr "Huch: Schlüssel ist ja gar nicht in der Trust-DB?\n"
#. update the ownertrust
-#: g10/trustdb.c:1232
+#: g10/trustdb.c:1246
#, c-format
msgid "insert trust record failed: %s\n"
msgstr "'trust record' einfügen fehlgeschlagen: %s\n"
#. error
-#: g10/trustdb.c:1238
+#: g10/trustdb.c:1252
#, c-format
msgid "error finding dir record: %s\n"
msgstr "Fehler beim Auffinden des Verz.Satzes: %s\n"
-#: g10/trustdb.c:1305
+#: g10/trustdb.c:1351
#, c-format
msgid "user '%s' not in trustdb - inserting\n"
msgstr "User '%s' ist nich in der 'Trust'-Datenbank - wird eingefügt\n"
-#: g10/trustdb.c:1308
+#: g10/trustdb.c:1354
#, c-format
msgid "failed to put '%s' into trustdb: %s\n"
msgstr "konnte '%s' nicht in die 'Trust'-Datenbank hineintun: %s\n"
-#: g10/trustdb.c:1355
+#: g10/trustdb.c:1404
#, c-format
msgid "%s: keyblock read problem: %s\n"
msgstr "%s: Schlüsselblock Leseproblem: %s\n"
-#: g10/trustdb.c:1369
+#: g10/trustdb.c:1418
#, c-format
msgid "%s: update failed: %s\n"
msgstr "%s: Änderung fehlgeschlagen: %s\n"
-#: g10/trustdb.c:1372
+#: g10/trustdb.c:1421
#, c-format
msgid "%s: updated\n"
msgstr "%s: geändert\n"
-#: g10/trustdb.c:1374
+#: g10/trustdb.c:1423
#, c-format
msgid "%s: okay\n"
msgstr "%s: In Ordnung\n"
-#: g10/trustdb.c:1389
+#: g10/trustdb.c:1438
#, c-format
msgid "lid %lu: dir record w/o key - skipped\n"
msgstr "lid %lu: Dir-Satz ohne Schlüssel - übergangen\n"
-#: g10/trustdb.c:1402
+#: g10/trustdb.c:1451
#, c-format
msgid "lid %lu: keyblock not found: %s\n"
msgstr "lid %lu: Schlüsselblock nicht gefunden: %s\n"
-#: g10/trustdb.c:1411 g10/trustdb.c:1480
+#: g10/trustdb.c:1460 g10/trustdb.c:1529
#, c-format
msgid "lid %lu: update failed: %s\n"
msgstr "lid %lu: Änderung fehlgeschlagen: %s\n"
-#: g10/trustdb.c:1417 g10/trustdb.c:1486
+#: g10/trustdb.c:1466 g10/trustdb.c:1535
#, c-format
msgid "lid %lu: updated\n"
msgstr "lid %lu: geändert\n"
-#: g10/trustdb.c:1421 g10/trustdb.c:1490
+#: g10/trustdb.c:1470 g10/trustdb.c:1539
#, c-format
msgid "lid %lu: okay\n"
msgstr "lid %lu: In Ordnung\n"
-#: g10/trustdb.c:1428 g10/trustdb.c:1496
+#: g10/trustdb.c:1477 g10/trustdb.c:1545
#, c-format
msgid "%lu keys processed\n"
msgstr "%lu Schlüssel bearbeitet\n"
-#: g10/trustdb.c:1430
+#: g10/trustdb.c:1479
#, c-format
msgid "\t%lu keys skipped\n"
msgstr "\t%lu Schlüssel übersprungen\n"
-#: g10/trustdb.c:1432 g10/trustdb.c:1498
+#: g10/trustdb.c:1481 g10/trustdb.c:1547
#, c-format
msgid "\t%lu keys with errors\n"
msgstr "\t%lu Schlüssel mit Fehlern\n"
-#: g10/trustdb.c:1434 g10/trustdb.c:1500
+#: g10/trustdb.c:1483 g10/trustdb.c:1549
#, c-format
msgid "\t%lu keys updated\n"
msgstr "\t%lu Schlüssel geändert\n"
-#: g10/trustdb.c:1464
+#: g10/trustdb.c:1513
#, c-format
msgid "lid ?: insert failed: %s\n"
msgstr "lid ?: Einfügen fehlgeschlagen: %s\n"
-#: g10/trustdb.c:1469
+#: g10/trustdb.c:1518
#, c-format
msgid "lid %lu: insert failed: %s\n"
msgstr "lid %lu: Einfügen fehlgeschlagen: %s\n"
-#: g10/trustdb.c:1475
+#: g10/trustdb.c:1524
#, c-format
msgid "lid %lu: inserted\n"
msgstr "lid %lu: eingefügt\n"
-#: g10/trustdb.c:1502
+#: g10/trustdb.c:1551
#, c-format
msgid "\t%lu keys inserted\n"
msgstr "\t%lu Schlüssel eingefügt\n"
-#: g10/trustdb.c:1505
+#: g10/trustdb.c:1554
#, c-format
msgid "enumerate keyblocks failed: %s\n"
msgstr "enumerate Schlüsselblock fehlgeschlagen: %s\n"
-#: g10/trustdb.c:1550
+#: g10/trustdb.c:1599
#, c-format
msgid "check_trust: search dir record failed: %s\n"
msgstr "check_trust: Suche nach Dir-Satz fehlgeschlagen: %s\n"
-#: g10/trustdb.c:1557
+#: g10/trustdb.c:1606
#, c-format
msgid "key %08lX: insert trust record failed: %s\n"
msgstr "Schlüssel %08lX: 'trust record' einfügen fehlgeschlagen: %s\n"
-#: g10/trustdb.c:1561
+#: g10/trustdb.c:1610
#, c-format
msgid "key %08lX.%lu: inserted into trustdb\n"
msgstr "Schlüssel %08lX.%lu: in \"trustdb\" eingefügt\n"
-#: g10/trustdb.c:1569
+#: g10/trustdb.c:1618
#, c-format
msgid "key %08lX.%lu: created in future (time warp or clock problem)\n"
msgstr ""
"Schlüssel %08lX.%lu: wurde in der Zukunft erzeugt (Zeitreise oder Uhren "
"stimmen nicht überein)\n"
-#: g10/trustdb.c:1576
+#: g10/trustdb.c:1625
#, c-format
msgid "key %08lX.%lu: expired at %s\n"
msgstr "Schlüssel %08lX.%lu: verfallen am %s\n"
-#: g10/trustdb.c:1584
+#: g10/trustdb.c:1633
#, c-format
msgid "key %08lX.%lu: trust check failed: %s\n"
msgstr "Schlüssel %08lX.%lu: Vertrauensprüfung fehlgeschlagen: %s\n"
-#: g10/trustdb.c:1753 g10/trustdb.c:1782 g10/trustdb.c:2521
+#: g10/trustdb.c:1820 g10/trustdb.c:1849 g10/trustdb.c:2588
msgid "WARNING: can't yet handle long pref records\n"
msgstr "WARNUNG: Lange 'Pref'-Records können noch nicht benutzt werden\n"
-#: g10/trustdb.c:1804
+#: g10/trustdb.c:1871
#, c-format
msgid "get_dir_record: search_record failed: %s\n"
msgstr "get_dir_record: search_record fehlgeschlagen: %s\n"
-#: g10/trustdb.c:1867
+#: g10/trustdb.c:1934
#, c-format
msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but marked as checked\n"
msgstr "Hinweis: sig rec %lu[%d] in hintlist of %lu but marked as checked\n"
-#: g10/trustdb.c:1871
+#: g10/trustdb.c:1938
#, c-format
msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but not marked\n"
msgstr "Hinweis: sig rec %lu[%d] in hintlist of %lu but not marked\n"
#. we need the dir record
-#: g10/trustdb.c:1878
+#: g10/trustdb.c:1945
#, c-format
msgid "sig rec %lu[%d] in hintlist of %lu does not point to a dir record\n"
msgstr "sig rec %lu[%d] in hintlist of %lu does not point to a dir record\n"
-#: g10/trustdb.c:1884
+#: g10/trustdb.c:1951
#, c-format
msgid "lid %lu: no primary key\n"
msgstr "lid %lu: kein Hauptschlüssel\n"
-#: g10/trustdb.c:1917
+#: g10/trustdb.c:1984
#, c-format
msgid "lid %lu: user id not found in keyblock\n"
msgstr "lid %lu: User-ID im Schlüsselblock nicht gefunden\n"
-#: g10/trustdb.c:1921
+#: g10/trustdb.c:1988
#, c-format
msgid "lid %lu: user id without signature\n"
msgstr "lid %lu: User-ID ohne Signatur\n"
-#: g10/trustdb.c:1928
+#: g10/trustdb.c:1995
#, c-format
msgid "lid %lu: self-signature in hintlist\n"
msgstr "lid %lu: Eigenbeglaubigung in 'hintlist'\n"
-#: g10/trustdb.c:1939 g10/trustdb.c:2658 g10/trustdb.c:2742
+#: g10/trustdb.c:2006 g10/trustdb.c:2725 g10/trustdb.c:2809
msgid "Valid certificate revocation"
msgstr "Gültiger Zerifikat-Widerruf"
-#: g10/trustdb.c:1940 g10/trustdb.c:2659 g10/trustdb.c:2743
+#: g10/trustdb.c:2007 g10/trustdb.c:2726 g10/trustdb.c:2810
msgid "Good certificate"
msgstr "Korrektes Zertifikat"
-#: g10/trustdb.c:1949
+#: g10/trustdb.c:2016
msgid "very strange: no public key\n"
msgstr "sehr seltsam: kein öffentlicher Schlüssel\n"
-#: g10/trustdb.c:1997
+#: g10/trustdb.c:2064
#, c-format
msgid "hintlist %lu[%d] of %lu does not point to a dir record\n"
msgstr "hintlist %lu[%d] of %lu zeigt nicht auf einen 'dir record'\n"
-#: g10/trustdb.c:2003
+#: g10/trustdb.c:2070
#, c-format
msgid "lid %lu does not have a key\n"
msgstr "lid %lu hat keinen Schlüssel\n"
-#: g10/trustdb.c:2013
+#: g10/trustdb.c:2080
#, c-format
msgid "lid %lu: can't get keyblock: %s\n"
msgstr "lid %lu: Schlüsselblock nicht verfügbar: %s\n"
-#: g10/trustdb.c:2070 g10/trustdb.c:2984
+#: g10/trustdb.c:2137 g10/trustdb.c:3051
#, c-format
msgid "tdbio_search_dir failed: %s\n"
msgstr "tdbio_search_dir fehlgeschlagen: %s\n"
-#: g10/trustdb.c:2223
+#: g10/trustdb.c:2290
#, c-format
msgid "key %08lX.%lu: Good subkey binding\n"
msgstr "Schlüssel %08lX.%lu: Korrekte Unterschlüssel-Anbindung\n"
-#: g10/trustdb.c:2229 g10/trustdb.c:2271
+#: g10/trustdb.c:2296 g10/trustdb.c:2338
#, c-format
msgid "key %08lX.%lu: Invalid subkey binding: %s\n"
msgstr "Schlüssel %08lX.%lu: Ungültige Unterschlüssel-Anbindung\n"
-#: g10/trustdb.c:2244
+#: g10/trustdb.c:2311
#, c-format
msgid "key %08lX.%lu: Valid key revocation\n"
msgstr "Schlüssel %08lX.%lu: Gültiger Schlüsselwiderruf\n"
-#: g10/trustdb.c:2250
+#: g10/trustdb.c:2317
#, c-format
msgid "key %08lX.%lu: Invalid key revocation: %s\n"
msgstr "Schlüssel %08lX.%lu: Ungültiger Schlüsselwiderruf: %s\n"
-#: g10/trustdb.c:2265
+#: g10/trustdb.c:2332
#, c-format
msgid "key %08lX.%lu: Valid subkey revocation\n"
msgstr "Schlüssel %08lX.%lu: Gültiger Unterschlüsselwiderruf\n"
-#: g10/trustdb.c:2365
+#: g10/trustdb.c:2432
msgid "Good self-signature"
msgstr "Korrekte Eigenbeglaubigung"
-#: g10/trustdb.c:2376
+#: g10/trustdb.c:2443
msgid "Invalid self-signature"
msgstr "Ungültige Eigenbeglaubigung"
-#: g10/trustdb.c:2386
+#: g10/trustdb.c:2453
msgid "Valid user ID revocation skipped due to a newer self signature\n"
-msgstr "Gültiger User-ID-Widerruf ignoriert, da eine neuere Eigenbeglaubigung vorliegt\n"
+msgstr ""
+"Gültiger User-ID-Widerruf ignoriert, da eine neuere Eigenbeglaubigung "
+"vorliegt\n"
-#: g10/trustdb.c:2393
+#: g10/trustdb.c:2460
msgid "Valid user ID revocation\n"
msgstr "Gültiger User-ID-Widerruf\n"
-#: g10/trustdb.c:2400
+#: g10/trustdb.c:2467
msgid "Invalid user ID revocation"
msgstr "Ungültiger User-ID-Widerruf"
-#: g10/trustdb.c:2484
+#: g10/trustdb.c:2551
msgid "Too many preferences"
msgstr "Zu viele Einstellungen"
-#: g10/trustdb.c:2498
+#: g10/trustdb.c:2565
msgid "Too many preference items"
msgstr "Zu viele Angaben zur Bevorzugung"
-#: g10/trustdb.c:2637
+#: g10/trustdb.c:2704
msgid "Duplicated certificate - deleted"
msgstr "Doppelte Zertifikate - entfernt"
-#: g10/trustdb.c:2670
+#: g10/trustdb.c:2737
msgid "Hmmm, public key lost?"
msgstr "Hmmm, öffentlicher Schüssel verloren?"
-#: g10/trustdb.c:2680 g10/trustdb.c:2763
+#: g10/trustdb.c:2747 g10/trustdb.c:2830
msgid "Invalid certificate revocation"
msgstr "Ungültiger Zertifikatswiderruf"
-#: g10/trustdb.c:2681 g10/trustdb.c:2764
+#: g10/trustdb.c:2748 g10/trustdb.c:2831
msgid "Invalid certificate"
msgstr "Ungültiges Zertifikat"
-#: g10/trustdb.c:2696
+#: g10/trustdb.c:2763
#, c-format
msgid "uid %08lX.%lu/%02X%02X: has shadow dir %lu but is not yet marked.\n"
-msgstr "uid %08lX.%lu/%02X%02X: hat \"shadow-dir\" %lu, aber ist noch nicht markiert.\n"
+msgstr ""
+"uid %08lX.%lu/%02X%02X: hat \"shadow-dir\" %lu, aber ist noch nicht "
+"markiert.\n"
-#: g10/trustdb.c:2710
+#: g10/trustdb.c:2777
#, c-format
msgid "sig record %lu[%d] points to wrong record.\n"
msgstr "Signatursatz %lu[%d] zeigt auf falschen Satz.\n"
#. that should never happen
-#: g10/trustdb.c:2954
+#: g10/trustdb.c:3021
#, c-format
msgid "insert_trust_record: keyblock not found: %s\n"
msgstr "insert_trust_record: Schlüsselblock nicht gefunden: %s\n"
-#: g10/trustdb.c:2972
+#: g10/trustdb.c:3039
msgid "did not use primary key for insert_trust_record()\n"
msgstr "Für insert_trust_record() wurde nicht der Hauptschlüssel benutzt\n"
#: g10/ringedit.c:293
#, c-format
msgid "%s: can't create keyring: %s\n"
msgstr "%s: Schlüsselbund kann nicht erzeugt werden: %s\n"
#: g10/ringedit.c:299 g10/ringedit.c:1264
#, c-format
msgid "%s: keyring created\n"
msgstr "%s: Schlüsselbund erstellt\n"
#: g10/ringedit.c:1449
msgid "WARNING: 2 files with confidential information exists.\n"
msgstr "Warnung: Zwei Dateien mit vertraulichem Inhalt vorhanden.\n"
#: g10/ringedit.c:1450
#, c-format
msgid "%s is the unchanged one\n"
msgstr "%s ist der Unveränderte\n"
#: g10/ringedit.c:1451
#, c-format
msgid "%s is the new one\n"
msgstr "%s ist der Neue\n"
#: g10/ringedit.c:1452
msgid "Please fix this possible security flaw\n"
msgstr "Bitte diesen potentiellen Sicherheitsmangel beseitigen\n"
#: g10/skclist.c:94
#, c-format
msgid "skipped '%s': %s\n"
msgstr "übersprungen '%s': %s\n"
#: g10/skclist.c:100
#, c-format
msgid ""
"skipped '%s': this is a PGP generated ElGamal key which is not secure for "
"signatures!\n"
msgstr ""
"'%s übersprungen: Dies ist ein durch PGP erzeugter ElGamal-Schlüssel. Das "
"ist für Signaturen NICHT sicher genug!\n"
#. do not overwrite
#: g10/openfile.c:58
#, c-format
msgid "File '%s' exists. "
msgstr "Datei '%s' existiert bereits. "
#: g10/openfile.c:60
msgid "Overwrite (y/N)? "
msgstr "Überschreiben (j/N)? "
#: g10/openfile.c:85
msgid "writing to stdout\n"
msgstr "Schreiben auf die Standardausgabe\n"
#: g10/openfile.c:134
#, c-format
msgid "assuming signed data in '%s'\n"
msgstr "die unterzeichneten Daten sind wohl in '%s'\n"
#: g10/openfile.c:181
#, c-format
msgid "%s: new options file created\n"
msgstr "%s: neue Optionendatei erstellt\n"
#: g10/encr-data.c:59
#, c-format
msgid "%s encrypted data\n"
msgstr "%s verschlüsselte Daten\n"
#: g10/encr-data.c:61
#, c-format
msgid "encrypted with unknown algorithm %d\n"
msgstr "Mit unbekanntem Verfahren verschlüsselt %d\n"
#: g10/encr-data.c:74
msgid ""
"WARNING: Message was encrypted with a weak key in the symmetric cipher.\n"
msgstr ""
"Warnung: Botschaft wurde mit einem unsicheren Schlüssel verschlüsselt.\n"
#: g10/seskey.c:52
msgid "weak key created - retrying\n"
msgstr "Unsicherer Schlüssel erzeugt - neuer Versuch\n"
#: g10/seskey.c:57
#, c-format
msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n"
msgstr ""
"Trotz %d-fachen Versuch konnte die Erzeugung eines unsicheren Schlüssels für "
"sym.Verschlüsselung nicht vermieden werden!\n"
+# "It's up to you to assign a value here; this value will never be exported\n"
+# "to any 3rd party. We need it to implement the web-of-trust; it has nothing\n"
+# "to do with the (implicitly created) web-of-certificates."
#. begin of list
-#: g10/helptext.c:45
-#"It's up to you to assign a value here; this value will never be exported\n"
-#"to any 3rd party. We need it to implement the web-of-trust; it has nothing\n"
-#"to do with the (implicitly created) web-of-certificates."
+#: g10/helptext.c:48
msgid "edit_ownertrust.value"
msgstr ""
-"SIE müssen hier einen Wert eingeben. Dieser Wert wird niemals an eine Dritte\n"
+"SIE müssen hier einen Wert eingeben. Dieser Wert wird niemals an eine "
+"Dritte\n"
"weitergegeben (exportiert) werden. Wir brauchen ihn zum Aufbau des\n"
"\"web-of-trust\", Er hat nichts mit dem (stillschweigend aufgebautem)\n"
"\"web-of-certificates\" zu tun."
-#: g10/helptext.c:51
-#"If you want to use this revoked key anyway, answer \"yes\"."
+# "If you want to use this revoked key anyway, answer \"yes\"."
+#: g10/helptext.c:54
msgid "revoked_key.override"
msgstr ""
"Wenn Sie diesen widerrufenen Schlüssel trotzdem benutzen wollen,\n"
"so antworten Sie mit \"ja\" oder schweigen für immer."
-#: g10/helptext.c:55
-#"If you want to use this untrusted key anyway, answer \"yes\"."
+# "If you want to use this untrusted key anyway, answer \"yes\"."
+#: g10/helptext.c:58
msgid "untrusted_key.override"
msgstr ""
"Wenn Sie diesen nichtvertruenswürdigen Schlüssel trotzdem benutzen wollen,\n"
"so antworten Sie mit \"ja\" oder schweigen Sie für immer."
-#: g10/helptext.c:59
-#"Enter the user id of the addresse to whom you want to send the message."
+# "Enter the user id of the addresse to whom you want to send the message."
+#: g10/helptext.c:62
msgid "pklist.user_id.enter"
-msgstr "Geben Sie die User-ID dessen ein, an den Sie die Botschaft senden wollen."
+msgstr ""
+"Geben Sie die User-ID dessen ein, an den Sie die Botschaft senden wollen."
-#: g10/helptext.c:63
+#: g10/helptext.c:66
msgid "keygen.algo"
msgstr ""
"Wählen Sie die zu verwendende Methode aus.\n"
"DSA (alias DSS) bedeutet \"digital signature algorithm\" (Digitales\n"
" Unterschrift-Verfahren). Es kann nur zum Unterschreiben und Beglaubigen\n"
" benutzt werden. Dies ist das empfohlene Verfahren, da dessen Überprüfung\n"
" wesentlich schneller abläuft, als die von \"ElGamal\".\n"
"\n"
"ElGamal ist ein Verfahren für Unterschrift, Beglaubigung und "
"Verschlüsselung\n"
" OpenPGP unterscheidet zwischen zwei Arten von ElGamal: eines nur zum\n"
" Unterschreiben/Beglaubigen und eines zusätzlich zum Verschlüsseln.\n"
" Eigentlich sind diese Arten identisch; allerdings müssen einige Parameter\n"
" auf eine besondere Art gewählt werden, um einen sicheren Schlüssel für\n"
" Unterschriften zu erzeugen. Dieses Programm macht dies zwar so, aber "
"andere\n"
" Programme sind nach OpenPGP-Spezifikation nicht verpflichtet die zweite "
"Art\n"
" (die mit zusätzlichem Verschlüsseln) zu verstehen.\n"
"\n"
"Der Hauptschlüssel (\"primary Key\") muß auf jeden Fall zum Unterschreiben "
"fähig\n"
"sein. Deshalb kann ein Nur-Verschlüssel-ElGamal-Schlüssel dafür nicht\n"
"verwendet werden.\n"
"Auch sollte man \"ElGamal in einem v3-Paket\" nicht verwenden, denn solch "
"ein\n"
"Schlüssel ist nicht mit anderen Programmen nach der OpenPGP-Spezifikation\n"
"verträglich."
-#: g10/helptext.c:80
-#"Enter the size of the key"
+#: g10/helptext.c:82
+#, fuzzy
+msgid "keygen.algo.elg_se"
+msgstr ""
+"Wählen Sie die zu verwendende Methode aus.\n"
+"DSA (alias DSS) bedeutet \"digital signature algorithm\" (Digitales\n"
+" Unterschrift-Verfahren). Es kann nur zum Unterschreiben und Beglaubigen\n"
+" benutzt werden. Dies ist das empfohlene Verfahren, da dessen Überprüfung\n"
+" wesentlich schneller abläuft, als die von \"ElGamal\".\n"
+"\n"
+"ElGamal ist ein Verfahren für Unterschrift, Beglaubigung und "
+"Verschlüsselung\n"
+" OpenPGP unterscheidet zwischen zwei Arten von ElGamal: eines nur zum\n"
+" Unterschreiben/Beglaubigen und eines zusätzlich zum Verschlüsseln.\n"
+" Eigentlich sind diese Arten identisch; allerdings müssen einige Parameter\n"
+" auf eine besondere Art gewählt werden, um einen sicheren Schlüssel für\n"
+" Unterschriften zu erzeugen. Dieses Programm macht dies zwar so, aber "
+"andere\n"
+" Programme sind nach OpenPGP-Spezifikation nicht verpflichtet die zweite "
+"Art\n"
+" (die mit zusätzlichem Verschlüsseln) zu verstehen.\n"
+"\n"
+"Der Hauptschlüssel (\"primary Key\") muß auf jeden Fall zum Unterschreiben "
+"fähig\n"
+"sein. Deshalb kann ein Nur-Verschlüssel-ElGamal-Schlüssel dafür nicht\n"
+"verwendet werden.\n"
+"Auch sollte man \"ElGamal in einem v3-Paket\" nicht verwenden, denn solch "
+"ein\n"
+"Schlüssel ist nicht mit anderen Programmen nach der OpenPGP-Spezifikation\n"
+"verträglich."
+
+# "Enter the size of the key"
+#: g10/helptext.c:89
msgid "keygen.size"
msgstr ""
"Wählen Sie die gewünschte Schlüssellänge.\n"
"\n"
"Ein langer Schlüssel bietet mehr Sicherheit, kostet aber auch mehr "
"Rechenzeit.\n"
"Ein kurzer Schlüssel ist nicht ganz so sicher, wird aber schneller "
"bearbeitet.\n"
"1024 Bit ist für den Heimgebrauch ein brauchbarer Wert. Wenn Sie aber z.B. "
"in\n"
"Atlanta, Georgia, USA für eine Limonandenfabrik arbeiten, und das Rezept\n"
"speichern wollen (\"SCHLEMMER!\"), so wären 2048 Bit kein schlechter Wert."
-#: g10/helptext.c:84
-#"Answer \"yes\" or \"no\""
+# "Answer \"yes\" or \"no\""
+#: g10/helptext.c:93
msgid "keygen.size.huge.okay"
msgstr "Geben Sie \"Ja\" oder \"Nein\" ein"
-#: g10/helptext.c:89
+#: g10/helptext.c:98
msgid "keygen.size.large.okay"
msgstr "Geben Sie \"Ja\" oder \"Nein\" ein"
-#: g10/helptext.c:94
+#: g10/helptext.c:103
msgid "keygen.valid"
msgstr "Geben Sie den erforderlichen Wert ein"
-#: g10/helptext.c:98
+#: g10/helptext.c:107
msgid "keygen.valid.okay"
msgstr "Geben Sie \"Ja\" oder \"Nein\" ein"
-#: g10/helptext.c:103
# "Enter the name of the key holder"
+#: g10/helptext.c:112
msgid "keygen.name"
msgstr "Geben Sie den Namen des Schlüsselinhabers ein"
-#: g10/helptext.c:108
-#"please enter an optional but highly suggested email address"
+# "please enter an optional but highly suggested email address"
+#: g10/helptext.c:117
msgid "keygen.email"
-msgstr "Geben Sie eine E-Mail-Adresse ein. Dies ist zwar nicht notwendig,\n"
+msgstr ""
+"Geben Sie eine E-Mail-Adresse ein. Dies ist zwar nicht notwendig,\n"
"aber empfehlenswert."
-#: g10/helptext.c:112
# "Please enter an optional comment"
+#: g10/helptext.c:121
msgid "keygen.comment"
msgstr "Geben Sie (bei Bedarf) einen Kommentar ein"
-#: g10/helptext.c:117
-#"N to change the name.\n"
-#"C to change the comment.\n"
-#"E to change the email address.\n"
-#"O to continue with key generation.\n"
-#"Q to to quit the key generation."
+# "N to change the name.\n"
+# "C to change the comment.\n"
+# "E to change the email address.\n"
+# "O to continue with key generation.\n"
+# "Q to to quit the key generation."
+#: g10/helptext.c:126
msgid "keygen.userid.cmd"
msgstr ""
"N um den Namen zu ändern.\n"
"K um den Kommentar zu ändern.\n"
"E um die E-Mail-Adresse zu ändern.\n"
"F um mit der Schlüsselerzeugung fortzusetzen.\n"
"B um die Schlüsselerzeugung abbrechen."
-#: g10/helptext.c:126
# "Answer \"yes\" (or just \"y\") if it is okay to generate the sub key."
+#: g10/helptext.c:135
msgid "keygen.sub.okay"
-msgstr "Geben Sie \"Ja\" (oder nur \"j\") ein, um den Unterschlüssel zu erzeugen."
+msgstr ""
+"Geben Sie \"Ja\" (oder nur \"j\") ein, um den Unterschlüssel zu erzeugen."
-#: g10/helptext.c:130
# "Answer \"yes\" or \"no\""
+#: g10/helptext.c:139
msgid "sign_uid.okay"
msgstr "Geben Sie \"Ja\" oder \"Nein\" ein"
-#: g10/helptext.c:135
# "Answer \"yes\" or \"no\""
+#: g10/helptext.c:144
msgid "change_passwd.empty.okay"
msgstr "Geben Sie \"Ja\" oder \"Nein\" ein"
-#: g10/helptext.c:140
# "Please enter \"help\" to see the list of commands."
+#: g10/helptext.c:149
msgid "keyedit.cmd"
msgstr "Geben Sie \"help\" ein, um die Liste der Befehle einzusehen."
-#: g10/helptext.c:144
# "Answer \"yes\" or \"no\""
+#: g10/helptext.c:153
msgid "keyedit.save.okay"
msgstr "Geben Sie \"Ja\" oder \"Nein\" ein"
-#: g10/helptext.c:149
+#: g10/helptext.c:158
msgid "keyedit.cancel.okay"
msgstr "Geben Sie \"Ja\" oder \"Nein\" ein"
-#: g10/helptext.c:153
# "Answer \"yes\" is you want to sign ALL the user IDs"
+#: g10/helptext.c:162
msgid "keyedit.sign_all.okay"
msgstr "Geben Sie \"Ja\" (oder nur \"j\") ein, um alle User-IDs zu beglaubigen"
-#: g10/helptext.c:157
# "Answer \"yes\" if you really want to delete this user ID.\n"
# "All ceritifcates are then also lost!"
+#: g10/helptext.c:166
msgid "keyedit.remove.uid.okay"
-msgstr "Geben Sie \"Ja\" (oder nur \"j\") ein, um diese User-ID zu LÖSCHEN.\n"
+msgstr ""
+"Geben Sie \"Ja\" (oder nur \"j\") ein, um diese User-ID zu LÖSCHEN.\n"
"Alle Zertifikate werden dann auch weg sein!"
-#: g10/helptext.c:162
# "Answer \"yes\" if it is okay to delete the subkey"
+#: g10/helptext.c:171
msgid "keyedit.remove.subkey.okay"
-msgstr "Geben Sie \"Ja\" (oder nur \"j\") ein, um diesen Unterschlüssel zu löschen"
+msgstr ""
+"Geben Sie \"Ja\" (oder nur \"j\") ein, um diesen Unterschlüssel zu löschen"
# ################################
# ####### Help msgids ############
# ################################
-#: g10/helptext.c:166
+#: g10/helptext.c:175
msgid "passphrase.enter"
msgstr ""
"Bitte geben Sie das Mantra ein. Dies ist ein geheimer Satz, der aus\n"
-"beliebigen Zeichen bestehen kann. Was Sie eingegeben wird nicht angezeigt.\n\n"
+"beliebigen Zeichen bestehen kann. Was Sie eingegeben wird nicht angezeigt.\n"
+"\n"
"Zur ihrer eigenen Sicherbeit benutzen Sie bitte einen Satz, den sie sich\n"
"gut merken könne, der aber nicht leicht zu erraten ist; Zitate und andere\n"
"bekannte Texte sind eine SCHLECHTE Wahl, da diese mit Sicherheit online\n"
"verfügbar sind und durch entsprechende Programme zum Raten des Mantras\n"
"benutzt werden. Sätze mit persönlicher Bedeutung, die auch noch durch\n"
-"falsche Groß-/Kleinschreibung und eingestreute Sonderzeichen verändert werden,\n"
+"falsche Groß-/Kleinschreibung und eingestreute Sonderzeichen verändert "
+"werden,\n"
"sind i.d.R. eine gute Wahl"
-#: g10/helptext.c:173
+#: g10/helptext.c:182
msgid "passphrase.repeat"
msgstr ""
"Um sicher zu gehen, daß Sie sich bei der Eingabe des Mantras nicht\n"
"vertippt haben, geben Sie diese bitte nochmal ein. Nur wenn beide Eingaben\n"
"übereinstimmen, wird das Mantra akzeptiert."
-#: g10/helptext.c:177
# "Give the name fo the file to which the signature applies"
+#: g10/helptext.c:186
msgid "detached_signature.filename"
-msgstr "Geben Sie den Namen der Datei an, zu dem die abgetrennte Unterschrift gehört"
+msgstr ""
+"Geben Sie den Namen der Datei an, zu dem die abgetrennte Unterschrift gehört"
-#: g10/helptext.c:181
# "Answer \"yes\" if it is okay to overwrite the file"
+#: g10/helptext.c:190
msgid "openfile.overwrite.okay"
msgstr "Geben Sie \"ja\" ein, wenn Sie die Datei überschreiben möchten"
-#: g10/helptext.c:195
+#: g10/helptext.c:204
msgid "No help available"
msgstr "Keine Hilfe vorhanden."
-#: g10/helptext.c:207
+#: g10/helptext.c:216
#, c-format
msgid "No help available for '%s'"
msgstr "Keine Hilfe für '%s' vorhanden."
#~ msgid "You will see a list of signators etc. here\n"
#~ msgstr "Sie sollten hier eigentlich eine Liste der Signierer sehen.\n"
#, fuzzy
#~ msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: good signature (3)\n"
#~ msgstr "Schlüssel %08lX: Ungültige Eigenbeglaubigung\n"
#, fuzzy
#~ msgid ""
#~ "key %08lX.%lu, uid %02X%02X, sig %08lX: very strange: no public key\n"
#~ msgstr "Schlüssel %08lX: Keine User-ID für Signatur\n"
#, fuzzy
#~ msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: invalid signature: %s\n"
#~ msgstr "Schlüssel %08lX: Ungültige Eigenbeglaubigung\n"
#, fuzzy
#~ msgid "key %08lX.%lu, uid %02X%02X: good self-signature\n"
#~ msgstr "Schlüssel %08lX: Ungültige Eigenbeglaubigung\n"
#, fuzzy
#~ msgid ""
#~ "key %08lX.%lu, uid %02X%02X, sig %08lX: duplicated signature - deleted\n"
#~ msgstr "Schlüssel %08lX: Ungültige Eigensignatur\n"
#, fuzzy
#~ msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: good signature (1)\n"
#~ msgstr "Schlüssel %08lX: Ungültige Eigensignatur\n"
#, fuzzy
#~ msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: weird: no public key\n"
#~ msgstr "Schlüssel %08lX: Keine User-ID für Signatur\n"
#, fuzzy
#~ msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: good signature (2)\n"
#~ msgstr "Schlüssel %08lX: Ungültige Eigensignatur\n"
#, fuzzy
#~ msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: no public key\n"
#~ msgstr "Schlüssel %08lX: Keine User-ID für Signatur\n"
#~ msgid "key %08lX: already in ultikey_table\n"
#~ msgstr "Schlüssel %08lX: bereits in der Tabelle der geheime Schlüssel\n"
#~ msgid "can't write keyring\n"
#~ msgstr "kann Schlüsselbund nicht schreiben\n"
#~ msgid "make a signature on a key in the keyring"
#~ msgstr "Schlüssel signieren"
#~ msgid "edit a key signature"
#~ msgstr "Bearbeiten der Signaturen eines Schlüssels"
#~ msgid "do not make any changes"
#~ msgstr "Keine wirklichen Änderungen durchführen"
#~ msgid ""
#~ "It's up to you to assign a value here; this value will never be exported\n"
#~ "to any 3rd party. We need it to implement the web-of-trust; it has nothing\n"
#~ "to do with the (implicitly created) web-of-certificates.\n"
#~ msgstr ""
#~ "Sie müssen selbt entscheiden, welchen Wert Sie hier eintragen; dieser Wert\n"
#~ "wird niemals an eine dritte Seite weitergegeben. Wir brauchen diesen Wert,\n"
#~ "um das \"Netz des Vertrauens\" aufzubauen. Dieses hat nichts mit dem "
#~ "(implizit\n"
#~ "erzeugten) \"Netz der Zertifikate\" zu tun.\n"
#~ msgid "public and secret subkey created.\n"
#~ msgstr "Öffentlicher und geheimer Schlüssel erzeugt.\n"
#~ msgid "No public key for %d signatures\n"
#~ msgstr "Kein öffentlicher Schlüssel für %d Signaturen\n"
#~ msgid "[User name not available] "
#~ msgstr "[Benuzername nicht verfügbar] "
#~ msgid "This is a BAD signature!\n"
#~ msgstr "Dies ist eine FALSCHE Signatur!\n"
#~ msgid "The signature could not be checked!\n"
#~ msgstr "Die Signatur konnte nicht geprüft werden!\n"
#~ msgid "Checking signatures of this public key certificate:\n"
#~ msgstr "Die Signaturen dieses Zertifikats werden überprüft:\n"
#~ msgid "Do you want to remove some of the invalid signatures? "
#~ msgstr "Möchten Sie einige der ungültigen Signaturen entfernen? "
#~ msgid "there is a secret key for this public key!\n"
#~ msgstr ""
#~ "Es gibt einen privaten Schlüssel zu diesem öffentlichen Schlüssel!\n"
#~ msgid "use option \"--delete-secret-key\" to delete it first.\n"
#~ msgstr ""
#~ "Benutzen Sie das Kommando \"--delete-secret-key\", um ihn vorab zu "
#~ "entfernen.\n"
#~ msgid "can't do that in batchmode without \"--yes\"\n"
#~ msgstr "Dies kann im Batchmodus ohne \"--yes\" nicht durchgeführt werden.\n"
#~ msgid "Delete this key from the keyring? "
#~ msgstr "Diesen Schlüssel aus dem Schlüsselbund löschen? "
#~ msgid "This is a secret key! - really delete? "
#~ msgstr "Dies ist ein privater Schlüssel! - Wirklich löschen? "
diff --git a/po/es_ES.po b/po/es_ES.po
index d52e11c44..a7d8c279a 100644
--- a/po/es_ES.po
+++ b/po/es_ES.po
@@ -1,3116 +1,3130 @@
# Spanish messages for gnupg
# Urko Lusa <ulusa@lacueva.ddns.org>, 1998
# I've tried to mantain the terminology used by Armando Ramos
# <armando@clerval.org> is his PGP 2.3.6i translation.
# I also got inspiration from it.po by Marco d'Itri <md@linux.it>
msgid ""
msgstr ""
-"POT-Creation-Date: 1998-12-10 20:11+0100\n"
+"POT-Creation-Date: 1998-12-17 18:30+0100\n"
"Content-Type: text/plain; charset=iso-8859-1\n"
"Date: 1998-11-13 10:49:25+0100\n"
"From: Urko Lusa <ulusa@lacueva.ddns.org>\n"
"Xgettext-Options: --default-domain=gnupg --directory=.. --add-comments "
"--keyword=_ --keyword=N_ --files-from=./POTFILES.in\n"
"Files: util/secmem.c util/argparse.c cipher/random.c cipher/rand-dummy.c "
"cipher/rand-unix.c cipher/rand-w32.c g10/g10.c g10/pkclist.c g10/keygen.c "
"g10/decrypt.c g10/encode.c g10/import.c g10/keyedit.c g10/keylist.c "
"g10/mainproc.c g10/passphrase.c g10/plaintext.c g10/pref.c g10/seckey-cert.c "
"g10/sig-check.c g10/sign.c g10/trustdb.c g10/verify.c\n"
#: util/secmem.c:77
msgid "Warning: using insecure memory!\n"
msgstr "Aviso: ¡se está usando memoria insegura!\n"
#: util/miscutil.c:143
msgid "yes"
msgstr "sí"
#: util/miscutil.c:144
msgid "yY"
msgstr "sS"
#: util/errors.c:54
msgid "General error"
msgstr "Error general"
#: util/errors.c:55
msgid "Unknown packet type"
msgstr "Formato desconocido"
#: util/errors.c:56
msgid "Unknown version"
msgstr "Versión desconocida"
#: util/errors.c:57
msgid "Unknown pubkey algorithm"
msgstr "Algoritmo de clave pública desconocido"
#: util/errors.c:58
msgid "Unknown digest algorithm"
msgstr "Algoritmo desconocido de resumen de mensaje"
#: util/errors.c:59
msgid "Bad public key"
msgstr "Clave pública incorrecta"
#: util/errors.c:60
msgid "Bad secret key"
msgstr "Clave secreta incorrecta"
#: util/errors.c:61
msgid "Bad signature"
msgstr "Firma incorrecta"
#: util/errors.c:62
msgid "Checksum error"
msgstr "Error en suma de comprobación"
#: util/errors.c:63
msgid "Bad passphrase"
msgstr "Contraseña incorrecta"
#: util/errors.c:64
msgid "Public key not found"
msgstr "Clave pública no encontrada"
#: util/errors.c:65
msgid "Unknown cipher algorithm"
msgstr "Algoritmo de cifrado desconocido"
#: util/errors.c:66
msgid "Can't open the keyring"
msgstr "No se puede abrir el anillo"
#: util/errors.c:67
msgid "Invalid packet"
msgstr "Valor no válido"
#: util/errors.c:68
msgid "Invalid armor"
msgstr "Armadura no válida"
#: util/errors.c:69
msgid "No such user id"
msgstr "No existe el identificativo de usuario"
#: util/errors.c:70
msgid "Secret key not available"
msgstr "Clave secreta no disponible"
#: util/errors.c:71
msgid "Wrong secret key used"
msgstr "Clave secreta incorrecta"
#: util/errors.c:72
msgid "Not supported"
msgstr "No soportado"
#: util/errors.c:73
msgid "Bad key"
msgstr "Clave incorrecta"
#: util/errors.c:74
msgid "File read error"
msgstr "Error de lectura"
#: util/errors.c:75
msgid "File write error"
msgstr "Error de escritura"
#: util/errors.c:76
msgid "Unknown compress algorithm"
msgstr "Algoritmo de compresión desconocido"
#: util/errors.c:77
msgid "File open error"
msgstr "Error al abrir fichero"
#: util/errors.c:78
msgid "File create error"
msgstr "Error al cerrar fichero"
#: util/errors.c:79
msgid "Invalid passphrase"
msgstr "Contraseña incorrecta"
#: util/errors.c:80
msgid "Unimplemented pubkey algorithm"
msgstr "Algoritmo de clave pública no implementado"
#: util/errors.c:81
msgid "Unimplemented cipher algorithm"
msgstr "Algoritmo de cifrado no implementado"
#: util/errors.c:82
msgid "Unknown signature class"
msgstr "Clase de firma desconocida"
#: util/errors.c:83
msgid "Trust database error"
msgstr "Error en la base de datos de confianza"
#: util/errors.c:84
msgid "Bad MPI"
msgstr "MPI incorrecto"
#: util/errors.c:85
msgid "Resource limit"
msgstr "Límite de recurso"
#: util/errors.c:86
msgid "Invalid keyring"
msgstr "Anillo no válido"
#: util/errors.c:87
msgid "Bad certificate"
msgstr "Certificado incorrecto"
#: util/errors.c:88
msgid "Malformed user id"
msgstr "Identificativo de usuario mal formado"
#: util/errors.c:89
msgid "File close error"
msgstr "Error al cerrar fichero"
#: util/errors.c:90
msgid "File rename error"
msgstr "Error al renombrar fichero"
#: util/errors.c:91
msgid "File delete error"
msgstr "Error al borrar fichero"
#: util/errors.c:92
msgid "Unexpected data"
msgstr "Datos inesperados"
#: util/errors.c:93
msgid "Timestamp conflict"
msgstr "Conflicto con sello de fecha"
#: util/errors.c:94
msgid "Unusable pubkey algorithm"
msgstr "Algoritmo de clave pública no utilizable"
#: util/errors.c:95
msgid "File exists"
msgstr "El fichero existe. "
#: util/errors.c:96
msgid "Weak key"
msgstr "Clave débil"
#: util/logger.c:178
#, fuzzy, c-format
msgid "... this is a bug (%s:%d:%s)\n"
msgstr "¡Oh! vaya... esto es un bug (%s:%d:%s)\n"
#: util/logger.c:184
#, c-format
msgid "you found a bug ... (%s:%d)\n"
msgstr "Ha encontrado Vd. un bug... (%s:%d)\n"
-#: cipher/random.c:412
+#: cipher/random.c:406
#, fuzzy
msgid "WARNING: using insecure random number generator!!\n"
msgstr "Aviso: ¡se está usando un generador de números aleatorios inseguro!\n"
-#: cipher/random.c:413
+#: cipher/random.c:407
msgid ""
"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"
msgstr ""
"EL generador de números aleatorios es sólo un apaño\n"
"para poder compilar. ¡No es en absoluto seguro!\n"
"\n"
"¡NO USE NINGÚN DATO GENERADO POR ESTE PROGRAMA!\n"
"\n"
-#: cipher/rndlinux.c:116
+#: cipher/rndlinux.c:118
#, c-format
msgid ""
"\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"
msgstr ""
"\n"
"No hay suficientes bytes aleatorios disponibles. Por favor, haga algún\n"
"otro trabajo para que el sistema pueda recolectar más entropía\n"
"(se necesitan %d bytes más).\n"
-#: g10/g10.c:159
+#: g10/g10.c:160
msgid ""
"@Commands:\n"
" "
msgstr ""
"@Comandos:\n"
" "
-#: g10/g10.c:162
+#: g10/g10.c:163
msgid "|[file]|make a signature"
msgstr "|[file]|hace una firma"
-#: g10/g10.c:163
+#: g10/g10.c:164
msgid "|[file]|make a clear text signature"
msgstr "|[file]|hace una firma en texto claro"
-#: g10/g10.c:164
+#: g10/g10.c:165
msgid "make a detached signature"
msgstr "hace una firma separada"
-#: g10/g10.c:165
+#: g10/g10.c:166
msgid "encrypt data"
msgstr "cifra datos"
-#: g10/g10.c:166
+#: g10/g10.c:167
msgid "encryption only with symmetric cipher"
msgstr "cifra sólo con un cifrado simétrico"
-#: g10/g10.c:167
+#: g10/g10.c:168
msgid "store only"
msgstr "sólo almacenar"
-#: g10/g10.c:168
+#: g10/g10.c:169
msgid "decrypt data (default)"
msgstr "descifra datos (predefinido)"
-#: g10/g10.c:169
+#: g10/g10.c:170
msgid "verify a signature"
msgstr "verifica una firma"
-#: g10/g10.c:171
+#: g10/g10.c:172
msgid "list keys"
msgstr "lista las claves"
-#: g10/g10.c:172
+#: g10/g10.c:173
msgid "list keys and signatures"
msgstr "lista las claves y firmas"
-#: g10/g10.c:173
+#: g10/g10.c:174
msgid "check key signatures"
msgstr "comprueba las firmas de las claves"
-#: g10/g10.c:174
+#: g10/g10.c:175
msgid "list keys and fingerprints"
msgstr "lista las claves y huellas dactilares"
-#: g10/g10.c:175
+#: g10/g10.c:176
msgid "list secret keys"
msgstr "lista las claves secretas"
-#: g10/g10.c:177
+#: g10/g10.c:178
msgid "generate a new key pair"
msgstr "genera un nuevo par de claves"
-#: g10/g10.c:179
+#: g10/g10.c:180
msgid "remove key from the public keyring"
msgstr "elimina la clave del anillo público"
-#: g10/g10.c:181
+#: g10/g10.c:182
msgid "sign or edit a key"
msgstr "firma o modifica una clave"
-#: g10/g10.c:182
+#: g10/g10.c:183
msgid "generate a revocation certificate"
msgstr "genera un certificado de revocación"
-#: g10/g10.c:184
+#: g10/g10.c:185
msgid "export keys"
msgstr "exporta las claves"
-#: g10/g10.c:187
+#: g10/g10.c:188
msgid "import/merge keys"
msgstr "importa/fusiona las claves"
-#: g10/g10.c:189
+#: g10/g10.c:190
msgid "list only the sequence of packets"
msgstr "lista sólo la secuencia de paquetes"
-#: g10/g10.c:192
+#: g10/g10.c:193
msgid "export the ownertrust values"
msgstr "exporta los valores de confianza"
-#: g10/g10.c:194
+#: g10/g10.c:195
msgid "import ownertrust values"
msgstr "importa los valores de confianza"
-#: g10/g10.c:196
+#: g10/g10.c:197
msgid "|[NAMES]|update the trust database"
msgstr "|[NOMBRES]|actualiza la base de datos de confianza"
-#: g10/g10.c:198
+#: g10/g10.c:199
msgid "|[NAMES]|check the trust database"
msgstr "|[NOMBRES]|comprueba la base de datos de confianza"
-#: g10/g10.c:199
+#: g10/g10.c:200
msgid "fix a corrupted trust database"
msgstr "arregla una base de datos de confianza dañada"
-#: g10/g10.c:200
+#: g10/g10.c:201
msgid "De-Armor a file or stdin"
msgstr "quita la armadura de un fichero o stdin"
-#: g10/g10.c:201
+#: g10/g10.c:202
msgid "En-Armor a file or stdin"
msgstr "crea la armadura a un fichero o stdin"
-#: g10/g10.c:202
+#: g10/g10.c:203
msgid "|algo [files]|print message digests"
msgstr "|algo [files]|imprime resúmenes de mensaje"
-#: g10/g10.c:203
+#: g10/g10.c:204
msgid "print all message digests"
msgstr "imprime todos los resúmenes de mensaje"
-#: g10/g10.c:210
+#: g10/g10.c:211
msgid ""
"@\n"
"Options:\n"
" "
msgstr ""
"@\n"
"Opciones:\n"
" "
-#: g10/g10.c:212
+#: g10/g10.c:213
msgid "create ascii armored output"
msgstr "crea una salida ascii con armadura"
-#: g10/g10.c:214
+#: g10/g10.c:215
msgid "use this user-id to sign or decrypt"
msgstr "usa este usuario para firmar o descifrar"
-#: g10/g10.c:215
+#: g10/g10.c:216
msgid "use this user-id for encryption"
msgstr "usa este usuario para cifrar"
-#: g10/g10.c:216
+#: g10/g10.c:217
msgid "|N|set compress level N (0 disables)"
msgstr "|N|establece nivel de compresión N (0 no comprime)"
-#: g10/g10.c:218
+#: g10/g10.c:219
msgid "use canonical text mode"
msgstr "usa modo de texto canónico"
-#: g10/g10.c:220
+#: g10/g10.c:221
msgid "use as output file"
msgstr "usa como fichero de salida"
-#: g10/g10.c:221
+#: g10/g10.c:222
msgid "verbose"
msgstr "prolijo"
-#: g10/g10.c:222
+#: g10/g10.c:223
msgid "be somewhat more quiet"
msgstr ""
-#: g10/g10.c:223
+#: g10/g10.c:224
msgid "force v3 signatures"
msgstr "fuerza firmas v3"
#. { oDryRun, "dry-run", 0, N_("do not make any changes") },
-#: g10/g10.c:225
+#: g10/g10.c:226
msgid "batch mode: never ask"
msgstr "proceso por lotes: nunca preguntar"
-#: g10/g10.c:226
+#: g10/g10.c:227
msgid "assume yes on most questions"
msgstr "asume \"sí\" en casi todas las preguntas"
-#: g10/g10.c:227
+#: g10/g10.c:228
msgid "assume no on most questions"
msgstr "asume \"no\" en casi todas las preguntas"
-#: g10/g10.c:228
+#: g10/g10.c:229
msgid "add this keyring to the list of keyrings"
msgstr "añade este anillo a la lista de anillos"
-#: g10/g10.c:229
+#: g10/g10.c:230
msgid "add this secret keyring to the list"
msgstr "añade este anillo secreto a la lista"
-#: g10/g10.c:230
+#: g10/g10.c:231
msgid "|NAME|use NAME as default secret key"
msgstr "|NOMBRE|usa NOMBRE como clave secreta por defecto"
-#: g10/g10.c:231
+#: g10/g10.c:232
#, fuzzy
msgid "|NAME|set terminal charset to NAME"
msgstr "|NOMBRE|usa el algoritmo de cifrado NOMBRE"
-#: g10/g10.c:232
+#: g10/g10.c:233
msgid "read options from file"
msgstr "lee opciones del fichero"
-#: g10/g10.c:234
+#: g10/g10.c:235
msgid "set debugging flags"
msgstr "establece los parámetros de depuración"
-#: g10/g10.c:235
+#: g10/g10.c:236
msgid "enable full debugging"
msgstr "habilita depuración completa"
-#: g10/g10.c:236
+#: g10/g10.c:237
msgid "|FD|write status info to this FD"
msgstr "|DF|escribe información de estado en descriptor DF"
-#: g10/g10.c:237
+#: g10/g10.c:238
msgid "do not write comment packets"
msgstr "no escribe paquetes de comentario"
-#: g10/g10.c:238
+#: g10/g10.c:239
msgid "(default is 1)"
msgstr "(por defecto es 1)"
-#: g10/g10.c:239
+#: g10/g10.c:240
msgid "(default is 3)"
msgstr "(por defecto es 3)"
-#: g10/g10.c:241
+#: g10/g10.c:242
msgid "|KEYID|ulimately trust this key"
msgstr ""
-#: g10/g10.c:242
+#: g10/g10.c:243
msgid "|FILE|load extension module FILE"
msgstr "|FICHERO|carga módulo de extensiones FICHERO"
-#: g10/g10.c:243
+#: g10/g10.c:244
msgid "emulate the mode described in RFC1991"
msgstr "emula el modo descrito en la RFC1991"
-#: g10/g10.c:244
+#: g10/g10.c:245
msgid "|N|use passphrase mode N"
msgstr "|N|usa modo de contraseña N"
-#: g10/g10.c:246
+#: g10/g10.c:247
msgid "|NAME|use message digest algorithm NAME for passphrases"
msgstr ""
"|NOMBRE|usa algoritmo de resumen de mensaje NOMBRE\n"
"para las contraseñas"
-#: g10/g10.c:248
+#: g10/g10.c:249
msgid "|NAME|use cipher algorithm NAME for passphrases"
msgstr ""
"|NOMBRE|usa el algoritmo de cifrado NOMBRE para las\n"
"contraseñas"
-#: g10/g10.c:250
+#: g10/g10.c:251
msgid "|NAME|use cipher algorithm NAME"
msgstr "|NOMBRE|usa el algoritmo de cifrado NOMBRE"
-#: g10/g10.c:251
+#: g10/g10.c:252
msgid "|NAME|use message digest algorithm NAME"
msgstr "|NOMBRE|usa algoritmo de resumen de mensaje NOMBRE"
-#: g10/g10.c:252
+#: g10/g10.c:253
msgid "|N|use compress algorithm N"
msgstr "|N|usa el algoritmo de compresión N"
-#: g10/g10.c:253
+#: g10/g10.c:254
msgid "throw keyid field of encrypted packets"
msgstr "elimina el campo keyid de los paquetes cifrados"
-#: g10/g10.c:261
+#: g10/g10.c:262
msgid ""
"@\n"
"Examples:\n"
"\n"
" -se -r Bob [file] sign and encrypt for user Bob\n"
" --clearsign [file] make a clear text signature\n"
" --detach-sign [file] make a detached signature\n"
" --list-keys [names] show keys\n"
" --fingerprint [names] show fingerprints\n"
msgstr ""
"@\n"
"Ejemplos:\n"
"\n"
" -se -r Bob [fichero] firma y cifra para el usuario Bob\n"
" --clearsign [fichero] hace una firma manteniendo el texto sin cifrar\n"
" --detach-sign [fichero] hace una firma separada\n"
" --list-keys [nombres] muestra las claves\n"
" --fingerprint [nombres] muestra las huellas dactilares\n"
-#: g10/g10.c:339
+#: g10/g10.c:341
msgid "Please report bugs to <gnupg-bugs@gnu.org>.\n"
msgstr "Por favor, informe de posibles \"bugs\" a <gnupg-bugs@gnu.org>.\n"
-#: g10/g10.c:344
+#: g10/g10.c:346
msgid "Usage: gpgm [options] [files] (-h for help)"
msgstr "Uso: gpgm [opciones] [ficheros] (-h para ayuda)"
-#: g10/g10.c:346
+#: g10/g10.c:348
msgid "Usage: gpg [options] [files] (-h for help)"
msgstr "Uso: gpg [opciones] [ficheros] (-h para ayuda)"
-#: g10/g10.c:351
+#: g10/g10.c:353
msgid ""
"Syntax: gpgm [options] [files]\n"
"GnuPG maintenance utility\n"
msgstr ""
"Sintaxis: gpgm [opciones] [ficheros]\n"
"Utilidad de mantenimiento de GnuPG\n"
-#: g10/g10.c:354
+#: g10/g10.c:356
msgid ""
"Syntax: gpg [options] [files]\n"
"sign, check, encrypt or decrypt\n"
"default operation depends on the input data\n"
msgstr ""
"Sintaxis: gpg [opciones] [ficheros]\n"
"firma, comprueba, cifra o descifra\n"
"la operación por defecto depende del tipo de datos de entrada\n"
-#: g10/g10.c:360
+#: g10/g10.c:362
msgid ""
"\n"
"Supported algorithms:\n"
msgstr ""
"\n"
"Algoritmos soportados:\n"
-#: g10/g10.c:435
+#: g10/g10.c:437
msgid "usage: gpgm [options] "
msgstr "uso: gpgm [opciones] "
-#: g10/g10.c:437
+#: g10/g10.c:439
msgid "usage: gpg [options] "
msgstr "uso: gpg [opciones] "
-#: g10/g10.c:478
+#: g10/g10.c:480
msgid "conflicting commands\n"
msgstr "comandos incompatibles\n"
-#: g10/g10.c:616
+#: g10/g10.c:618
#, fuzzy, c-format
msgid "NOTE: no default option file '%s'\n"
msgstr "nota: no existe fichero de opciones predefinido '%s'\n"
-#: g10/g10.c:620
+#: g10/g10.c:622
#, c-format
msgid "option file '%s': %s\n"
msgstr "fichero de opciones '%s': %s\n"
-#: g10/g10.c:627
+#: g10/g10.c:629
#, c-format
msgid "reading options from '%s'\n"
msgstr "leyendo opciones desde '%s'\n"
-#: g10/g10.c:776
+#: g10/g10.c:782
#, fuzzy, c-format
msgid "%s is not a valid character set\n"
msgstr "Caracter no válido en el comentario\n"
-#: g10/g10.c:810 g10/g10.c:822
+#: g10/g10.c:817 g10/g10.c:829
msgid "selected cipher algorithm is invalid\n"
msgstr "el algoritmo de cifra seleccionado no es válido\n"
-#: g10/g10.c:816 g10/g10.c:828
+#: g10/g10.c:823 g10/g10.c:835
msgid "selected digest algorithm is invalid\n"
msgstr "el algoritmo de resumen seleccionado no es válido\n"
-#: g10/g10.c:831
+#: g10/g10.c:838
#, c-format
msgid "compress algorithm must be in range %d..%d\n"
msgstr "el algoritmo de compresión debe estar en el rango %d-%d\n"
-#: g10/g10.c:833
+#: g10/g10.c:840
msgid "completes-needed must be greater than 0\n"
msgstr "completes-needed debe ser mayor que 0\n"
-#: g10/g10.c:835
+#: g10/g10.c:842
msgid "marginals-needed must be greater than 1\n"
msgstr "marginals-needed debe ser mayor que 1\n"
-#: g10/g10.c:837
+#: g10/g10.c:844
msgid "max-cert-depth must be in range 1 to 255\n"
msgstr ""
-#: g10/g10.c:840
+#: g10/g10.c:847
#, fuzzy
msgid "NOTE: simple S2K mode (0) is strongly discouraged\n"
msgstr "nota: el modo S2K simple (0) no es nada recomendable\n"
-#: g10/g10.c:844
+#: g10/g10.c:851
msgid "invalid S2K mode; must be 0, 1 or 3\n"
msgstr "modo S2K incorrecto; debe ser 0, 1 o 3\n"
-#: g10/g10.c:927
+#: g10/g10.c:934
#, c-format
msgid "failed to initialize the TrustDB: %s\n"
msgstr "inicialización de la base de datos de confianza '%s' fallida\n"
-#: g10/g10.c:933
+#: g10/g10.c:940
msgid "--store [filename]"
msgstr "--store [nombre_fichero]"
-#: g10/g10.c:941
+#: g10/g10.c:948
msgid "--symmetric [filename]"
msgstr "--symmetric [nombre_fichero]"
-#: g10/g10.c:949
+#: g10/g10.c:956
msgid "--encrypt [filename]"
msgstr "--encrypt [nombre_fichero]"
-#: g10/g10.c:962
+#: g10/g10.c:969
msgid "--sign [filename]"
msgstr "--sign [nombre_fichero]"
-#: g10/g10.c:975
+#: g10/g10.c:982
msgid "--sign --encrypt [filename]"
msgstr "--sign --encrypt [nombre_fichero]"
-#: g10/g10.c:989
+#: g10/g10.c:996
msgid "--clearsign [filename]"
msgstr "--clearsign [nombre_fichero]"
-#: g10/g10.c:1001
+#: g10/g10.c:1008
msgid "--decrypt [filename]"
msgstr "--decrypt [nombre_fichero]"
-#: g10/g10.c:1010
+#: g10/g10.c:1017
#, fuzzy
msgid "--edit-key username [commands]"
msgstr "--edit-key nombre_usuario"
-#: g10/g10.c:1026
+#: g10/g10.c:1033
msgid "--delete-secret-key username"
msgstr "--delete-secret-key nombre_usuario"
-#: g10/g10.c:1029
+#: g10/g10.c:1036
msgid "--delete-key username"
msgstr "--delete-key nombre_usuario"
-#: g10/encode.c:216 g10/g10.c:1052 g10/sign.c:301
+#: g10/encode.c:216 g10/g10.c:1059 g10/sign.c:301
#, c-format
msgid "can't open %s: %s\n"
msgstr "no puede abrirse '%s': %s\n"
-#: g10/g10.c:1063
+#: g10/g10.c:1070
msgid "-k[v][v][v][c] [userid] [keyring]"
msgstr "-k[v][v][v][c] [id_usuario] [anillo]"
-#: g10/g10.c:1120
+#: g10/g10.c:1127
#, c-format
msgid "dearmoring failed: %s\n"
msgstr "eliminación de armadura fallida: %s\n"
-#: g10/g10.c:1128
+#: g10/g10.c:1135
#, c-format
msgid "enarmoring failed: %s\n"
msgstr "creación de armadura fallida: %s\n"
-#: g10/g10.c:1194
+#: g10/g10.c:1201
#, c-format
msgid "invalid hash algorithm '%s'\n"
msgstr "algoritmo de distribución no válido '%s'\n"
-#: g10/g10.c:1273
+#: g10/g10.c:1280
msgid "[filename]"
msgstr "[nombre_fichero]"
-#: g10/g10.c:1277
+#: g10/g10.c:1284
msgid "Go ahead and type your message ...\n"
msgstr ""
-#: g10/decrypt.c:59 g10/g10.c:1280 g10/verify.c:66
+#: g10/decrypt.c:59 g10/g10.c:1287 g10/verify.c:66
#, c-format
msgid "can't open '%s'\n"
msgstr "no puede abrirse '%s'\n"
#: g10/armor.c:344 g10/armor.c:391
msgid "armor header: "
msgstr "cabecera de armadura: "
#: g10/armor.c:355
msgid "invalid clearsig header\n"
msgstr "cabecera de firma clara no válida\n"
#: g10/armor.c:382
msgid "invalid armor header: "
msgstr "cabecera de armadura no válida: "
#: g10/armor.c:460
#, c-format
msgid "armor: %s\n"
msgstr "armadura: %s\n"
#: g10/armor.c:533
msgid "invalid dash escaped line: "
msgstr "Línea con guiones no válida: "
#: g10/armor.c:602
msgid "invalid clear text header: "
msgstr "cabecera de texto claro no válida: "
#: g10/armor.c:845
#, c-format
msgid "invalid radix64 character %02x skipped\n"
msgstr "caracteres no válidos radix64 %02x ignorados\n"
#: g10/armor.c:878
msgid "premature eof (no CRC)\n"
msgstr "Fin de fichero prematuro\n"
#: g10/armor.c:897
msgid "premature eof (in CRC)\n"
msgstr "Fin de suma de comprobación prematuro\n"
#: g10/armor.c:901
msgid "malformed CRC\n"
msgstr "Suma de comprobación mal creada\n"
#: g10/armor.c:905
#, c-format
msgid "CRC error; %06lx - %06lx\n"
msgstr "Error en suma de comprobación: %06lx - %06lx\n"
#: g10/armor.c:924
msgid "premature eof (in Trailer)\n"
msgstr ""
#: g10/armor.c:928
msgid "error in trailer line\n"
msgstr ""
#: g10/armor.c:1182
msgid "no valid RFC1991 or OpenPGP data found.\n"
msgstr "RFC1991 no válida o datos OpenPGP no encontrados\n"
-#: g10/pkclist.c:121
+#: g10/pkclist.c:138
#, fuzzy, c-format
msgid ""
"No trust value assigned to %lu:\n"
"%4u%c/%08lX %s \""
msgstr ""
"No hay confianza definida para el propietario %lu:\n"
"%4u%c/%08lX %s \""
-#: g10/pkclist.c:131
+#: g10/pkclist.c:148
msgid ""
"Please decide how far you trust this user to correctly\n"
"verify other users' keys (by looking at passports,\n"
"checking fingerprints from different sources...)?\n"
"\n"
" 1 = Don't know\n"
" 2 = I do NOT trust\n"
" 3 = I trust marginally\n"
" 4 = I trust fully\n"
" s = please show me more information\n"
msgstr ""
"Por favor, decida su nivel de confianza para este que usuario\n"
"verifique las claves de otros usuarios (mirando pasaportes,\n"
"comprobando huellas dactilares en diferentes fuentes...)\n"
"\n"
" 1 = No lo sé\n"
" 2 = NO me fío\n"
" 3 = Me fío marginalmente\n"
" 4 = Me fío completamente\n"
" i = Mostrar más información\n"
-#: g10/pkclist.c:140
+#: g10/pkclist.c:157
msgid " m = back to the main menu\n"
msgstr " m = volver al menú principal\n"
+#: g10/pkclist.c:159
+msgid " q = quit\n"
+msgstr ""
+
#. a string with valid answers
-#: g10/pkclist.c:145
-msgid "sSmM"
-msgstr "iImM"
+#: g10/pkclist.c:164
+#, fuzzy
+msgid "sSmMqQ"
+msgstr "iImMqQ"
-#: g10/pkclist.c:149
+#: g10/pkclist.c:168
msgid "Your decision? "
msgstr "Su decisión: "
-#: g10/pkclist.c:169
+#: g10/pkclist.c:188
msgid "Certificates leading to an ultimately trusted key:\n"
msgstr ""
-#: g10/pkclist.c:197
+#: g10/pkclist.c:221
msgid ""
"Could not find a valid trust path to the key. Let's see whether we\n"
"can assign some missing owner trust values.\n"
"\n"
msgstr ""
"No puede encontrarse una ruta de confianza váida para esta clave. Veamos\n"
"si es posible asignar algunos valores de confianza perdidos.\n"
"\n"
-#: g10/pkclist.c:219
+#: g10/pkclist.c:251
msgid ""
"No path leading to one of our keys found.\n"
"\n"
msgstr ""
-#: g10/pkclist.c:221
+#: g10/pkclist.c:253
msgid ""
"No certificates with undefined trust found.\n"
"\n"
msgstr ""
-#: g10/pkclist.c:223
+#: g10/pkclist.c:255
#, fuzzy
msgid ""
"No trust values changed.\n"
"\n"
msgstr ""
"No se cambió ningún valor de confianza.\n"
"\n"
-#: g10/pkclist.c:238
+#: g10/pkclist.c:270
#, fuzzy, c-format
msgid "key %08lX: key has been revoked!\n"
msgstr "clave %08lX: aceptada como clave secreta.\n"
-#: g10/pkclist.c:244 g10/pkclist.c:335
+#: g10/pkclist.c:276 g10/pkclist.c:369
msgid "Use this key anyway? "
msgstr "¿Usar esta clave de todas formas? "
-#: g10/pkclist.c:266
+#: g10/pkclist.c:298
#, fuzzy, c-format
msgid "%08lX: key has expired\n"
msgstr "Nota: ¡Esta clave está caducada!\n"
-#: g10/pkclist.c:272
+#: g10/pkclist.c:304
#, c-format
msgid "%08lX: no info to calculate a trust probability\n"
msgstr ""
-#: g10/pkclist.c:288
+#: g10/pkclist.c:322
#, fuzzy, c-format
msgid "%08lX: We do NOT trust this key\n"
msgstr "ATENCIÓN: ¡Esta firma NO es de confianza!\n"
-#: g10/pkclist.c:294
+#: g10/pkclist.c:328
#, c-format
msgid ""
"%08lX: It is not sure that this key really belongs to the owner\n"
"but it is accepted anyway\n"
msgstr ""
-#: g10/pkclist.c:300
+#: g10/pkclist.c:334
msgid "This key probably belongs to the owner\n"
msgstr ""
-#: g10/pkclist.c:305
+#: g10/pkclist.c:339
msgid "This key belongs to us\n"
msgstr ""
-#: g10/pkclist.c:330
+#: g10/pkclist.c:364
msgid ""
"It is NOT certain that the key belongs to its owner.\n"
"If you *really* know what you are doing, you may answer\n"
"the next question with yes\n"
"\n"
msgstr ""
"No es seguro que la clave pertenezca a su propietario.\n"
"Si *realmente* sabe lo que está haciendo, puede contestar\n"
"\"sí\" a la siguiente pregunta.\n"
"\n"
-#: g10/pkclist.c:339
+#: g10/pkclist.c:373
msgid "WARNING: Using untrusted key!\n"
msgstr "ATENCIÓN: ¡Usando una clave no fiable!\n"
-#: g10/pkclist.c:375
+#: g10/pkclist.c:409
msgid "WARNING: This key has been revoked by its owner!\n"
msgstr "ATENCIÓN: ¡Esta clave ha sido revocada por su propietario!\n"
-#: g10/pkclist.c:376
+#: g10/pkclist.c:410
msgid " This could mean that the signature is forgery.\n"
msgstr " Esto puede significar que la firma está falsificada.\n"
-#: g10/pkclist.c:397
+#: g10/pkclist.c:431
msgid "Note: This key has expired!\n"
msgstr "Nota: ¡Esta clave está caducada!\n"
-#: g10/pkclist.c:404
+#: g10/pkclist.c:438
msgid "WARNING: This key is not certified with a trusted signature!\n"
msgstr ""
"ATENCIÓN: ¡Esta clave no está certificada por una firma de confianza!\n"
-#: g10/pkclist.c:406
+#: g10/pkclist.c:440
msgid ""
" There is no indication that the signature belongs to the owner.\n"
msgstr " No hay indicios de que la firma pertenezca al propietario.\n"
-#: g10/pkclist.c:421
+#: g10/pkclist.c:456
msgid "WARNING: We do NOT trust this key!\n"
msgstr "ATENCIÓN: ¡Esta firma NO es de confianza!\n"
-#: g10/pkclist.c:422
+#: g10/pkclist.c:457
msgid " The signature is probably a FORGERY.\n"
msgstr " La firma es probablemente una FALSIFICACIÓN.\n"
-#: g10/pkclist.c:429
+#: g10/pkclist.c:464
msgid ""
"WARNING: This key is not certified with sufficiently trusted signatures!\n"
msgstr ""
"AVISO: ¡Esta clave no está certificada con suficientes firmas de confianza!\n"
-#: g10/pkclist.c:432
+#: g10/pkclist.c:467
msgid " It is not certain that the signature belongs to the owner.\n"
msgstr " No es seguro que la firma pertenezca al propietario.\n"
-#: g10/pkclist.c:477
+#: g10/pkclist.c:512
msgid ""
"You did not specify a user ID. (you may use \"-r\")\n"
"\n"
msgstr ""
"No se ha especificado un ID de usuario (puede usar \"-r\")\n"
"\n"
-#: g10/pkclist.c:482
+#: g10/pkclist.c:517
msgid "Enter the user ID: "
msgstr "Introduzca el ID de usuario: "
-#: g10/pkclist.c:493
+#: g10/pkclist.c:528
msgid "No such user ID.\n"
msgstr "ID de usuario inexistente.\n"
-#: g10/pkclist.c:527 g10/pkclist.c:554
+#: g10/pkclist.c:562 g10/pkclist.c:589
#, c-format
msgid "%s: skipped: %s\n"
msgstr "%s: ignorado: %s\n"
-#: g10/pkclist.c:535
+#: g10/pkclist.c:570
#, c-format
msgid "%s: error checking key: %s\n"
msgstr "%s: error comprobando la clave: %s\n"
-#: g10/pkclist.c:561
+#: g10/pkclist.c:596
msgid "no valid addressees\n"
msgstr "no hay direcciones válidas\n"
#: g10/keygen.c:124
msgid "writing self signature\n"
msgstr "escribiendo autofirma\n"
#: g10/keygen.c:162
msgid "writing key binding signature\n"
msgstr ""
#: g10/keygen.c:388
msgid "Please select what kind of key you want:\n"
msgstr "Por favor seleccione tipo de clave deseado:\n"
#: g10/keygen.c:390
#, c-format
msgid " (%d) DSA and ElGamal (default)\n"
msgstr " (%d) DSA y ElGamal (por defecto)\n"
#: g10/keygen.c:391
#, c-format
msgid " (%d) DSA (sign only)\n"
msgstr " (%d) DSA (sólo firma)\n"
#: g10/keygen.c:393
#, c-format
msgid " (%d) ElGamal (encrypt only)\n"
msgstr " (%d) ElGamal (sólo cifrado)\n"
#: g10/keygen.c:394
#, c-format
msgid " (%d) ElGamal (sign and encrypt)\n"
msgstr " (%d) ElGamal (firma y cifrado)\n"
#: g10/keygen.c:396
#, c-format
msgid " (%d) ElGamal in a v3 packet\n"
msgstr " (%d) ElGamal en un paquete v3\n"
#: g10/keygen.c:401
msgid "Your selection? "
msgstr "Su elección: "
#: g10/keygen.c:411
#, fuzzy
msgid "Do you really want to create a sign and encrypt key? "
msgstr "¿Borrar realmente las claves seleccionadas? "
#: g10/keygen.c:432
msgid "Invalid selection.\n"
msgstr "Elección no válida.\n"
#: g10/keygen.c:444
#, c-format
msgid ""
"About to generate a new %s keypair.\n"
" minimum keysize is 768 bits\n"
" default keysize is 1024 bits\n"
" highest suggested keysize is 2048 bits\n"
msgstr ""
"Listo para generar un nuevo par de claves %s.\n"
" el tamaño mínimo es 768 bits\n"
" el tamaño por defecto es 1024 bits\n"
" el tamaño máximo recomendado en 2048 bits\n"
#: g10/keygen.c:451
msgid "What keysize do you want? (1024) "
msgstr "¿De qué tamaño quiere la clave (1024)? "
#: g10/keygen.c:456
msgid "DSA only allows keysizes from 512 to 1024\n"
msgstr "DSA sólo permite tamaños desde 512 a 1024\n"
#: g10/keygen.c:458
msgid "keysize too small; 768 is smallest value allowed.\n"
msgstr "tamaño insuficiente; 768 es el valor mínimo permitido\n"
#: g10/keygen.c:461
msgid ""
"Keysizes larger than 2048 are not suggested because\n"
"computations take REALLY long!\n"
msgstr ""
"No se recomiendan claves de más de 2048 bits porque\n"
"el tiempo de computación es REALMENTE largo.\n"
#: g10/keygen.c:464
msgid "Are you sure that you want this keysize? "
msgstr "¿Seguro que quiere una clave de este tamaño? "
#: g10/keygen.c:465
msgid ""
"Okay, but keep in mind that your monitor and keyboard radiation is also very "
"vulnerable to attacks!\n"
msgstr ""
"De acuerdo, ¡pero tenga en cuenta que las radiaciones de su monitor y "
"teclado\n"
"también son vulnerables a un ataque!\n"
#: g10/keygen.c:473
msgid "Do you really need such a large keysize? "
msgstr "¿De verdad necesita una clave tan grande? "
#: g10/keygen.c:479
#, c-format
msgid "Requested keysize is %u bits\n"
msgstr "El tamaño requerido es de %u bits\n"
#: g10/keygen.c:482 g10/keygen.c:486
#, c-format
msgid "rounded up to %u bits\n"
msgstr "redondeados a %u bits\n"
#: g10/keygen.c:499
msgid ""
"Please specify how long the key should be valid.\n"
" 0 = key does not expire\n"
" <n> = key expires in n days\n"
" <n>w = key expires in n weeks\n"
" <n>m = key expires in n months\n"
" <n>y = key expires in n years\n"
msgstr ""
"Por favor, especifique el período de validez de la clave.\n"
" 0 = la clave nunca caduca\n"
" <n> = la clave caduca en n días\n"
" <n>w = la clave caduca en n semanas\n"
" <n>m = la clave caduca en n meses\n"
" <n>y = la clave caduca en n años\n"
#: g10/keygen.c:514
msgid "Key is valid for? (0) "
msgstr "¿Validez de la clave (0)? "
#: g10/keygen.c:525
msgid "invalid value\n"
msgstr "valor no válido\n"
#: g10/keygen.c:530
msgid "Key does not expire at all\n"
msgstr "La clave nunca caduca\n"
#. print the date when the key expires
#: g10/keygen.c:536
#, c-format
msgid "Key expires at %s\n"
msgstr "La clave caduca el %s\n"
#: g10/keygen.c:542
msgid "Is this correct (y/n)? "
msgstr "¿Es correcto (s/n)? "
#: g10/keygen.c:584
msgid ""
"\n"
"You need a User-ID to identify your key; the software constructs the user "
"id\n"
"from Real Name, Comment and Email Address in this form:\n"
" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n"
"\n"
msgstr ""
"\n"
"Necesita un identificativo de usuario para identificar su clave. El "
"programa\n"
"construye el identificativo a partir del Nombre Real, Comentario y "
"Dirección\n"
"de Correo Electrónico de esta forma:\n"
" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n"
"\n"
#: g10/keygen.c:595
msgid "Real name: "
msgstr "Nombre y apellidos: "
#: g10/keygen.c:599
msgid "Invalid character in name\n"
msgstr "Caracter no válido en el nombre\n"
#: g10/keygen.c:601
msgid "Name may not start with a digit\n"
msgstr "El nombre no puede empezar con un número\n"
#: g10/keygen.c:603
msgid "Name must be at least 5 characters long\n"
msgstr "El nombre debe tener al menos 5 caracteres\n"
#: g10/keygen.c:611
msgid "Email address: "
msgstr "Dirección de correo electrónico: "
#: g10/keygen.c:623
msgid "Not a valid email address\n"
msgstr "Dirección no válida\n"
#: g10/keygen.c:631
msgid "Comment: "
msgstr "Comentario: "
#: g10/keygen.c:637
msgid "Invalid character in comment\n"
msgstr "Caracter no válido en el comentario\n"
#: g10/keygen.c:657
#, c-format
msgid ""
"You selected this USER-ID:\n"
" \"%s\"\n"
"\n"
msgstr ""
"Ha seleccionado este identificativo de usuario:\n"
" \"%s\"\n"
"\n"
#: g10/keygen.c:660
msgid "NnCcEeOoQq"
msgstr "NnCcDdVvSs"
#: g10/keygen.c:670
msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? "
msgstr "¿Cambia (N)ombre, (C)omentario, (D)irección o (V)ale/(S)alir? "
#: g10/keygen.c:722
msgid ""
"You need a Passphrase to protect your secret key.\n"
"\n"
msgstr ""
"Necesita una contraseña para proteger su clave secreta.\n"
"\n"
#: g10/keyedit.c:389 g10/keygen.c:730
msgid "passphrase not correctly repeated; try again.\n"
msgstr "contraseña repetida incorrecta, inténtelo de nuevo.\n"
#: g10/keygen.c:736
msgid ""
"You don't want a passphrase - this is probably a *bad* idea!\n"
"I will do it anyway. You can change your passphrase at any time,\n"
"using this program with the option \"--edit-key\".\n"
"\n"
msgstr ""
"No ha especificado contraseña. Esto es probablemente una *mala* idea.\n"
"Si más tarde quiere añadir una, puede hacerlo usando este programa con\n"
"la opción \"--edit-key\".\n"
"\n"
#: g10/keygen.c:757
msgid ""
"We need to generate a lot of random bytes. It is a good idea to perform\n"
"some other action (work in another window, move the mouse, utilize the\n"
"network and the disks) during the prime generation; this gives the random\n"
"number generator a better chance to gain enough entropy.\n"
msgstr ""
"Es necesario generar muchos bytes aleatorios. Es una buena idea realizar\n"
"alguna otra tarea (trabajar en otra ventana/consola, mover el ratón, usar\n"
"la red y los discos) durante la generación de números primos. Esto da al\n"
"generador de números aleatorios mayor oportunidad de recoger suficiente\n"
"entropía.\n"
#: g10/keygen.c:827
msgid "Key generation can only be used in interactive mode\n"
msgstr "La creación de claves sólo es posible en modo interactivo\n"
#: g10/keygen.c:835
msgid "DSA keypair will have 1024 bits.\n"
msgstr "El par de claves DSA tendrá 1024 bits.\n"
#: g10/keygen.c:841
msgid "Key generation cancelled.\n"
msgstr "Creación de claves cancelada.\n"
#: g10/keygen.c:851
#, c-format
msgid "writing public certificate to '%s'\n"
msgstr "escribiendo certificado público en '%s'\n"
#: g10/keygen.c:852
#, c-format
msgid "writing secret certificate to '%s'\n"
msgstr "escribiendo certificado privado en '%s'\n"
#: g10/keygen.c:929
msgid "public and secret key created and signed.\n"
msgstr "Claves pública y secreta creadas y firmadas.\n"
#: g10/keygen.c:931
msgid ""
"Note that this key cannot be used for encryption. You may want to use\n"
"the command \"--add-key\" to generate a secondary key for this purpose.\n"
msgstr ""
"Tenga en cuenta que esta clave no puede ser usada para cifrado. Puede usar\n"
"el comando \"--add-key\" para crear una clave secundaria con este "
"propósito.\n"
#: g10/keygen.c:945 g10/keygen.c:1030
#, c-format
msgid "Key generation failed: %s\n"
msgstr "Creación de la clave fallida: %s\n"
#: g10/keygen.c:1008
msgid "Really create? "
msgstr "¿Crear de verdad? "
#: g10/encode.c:88 g10/openfile.c:81 g10/openfile.c:158 g10/tdbio.c:445
#: g10/tdbio.c:504
#, c-format
msgid "%s: can't open: %s\n"
msgstr "%s: no puede abrirse: %s\n"
#: g10/encode.c:107
#, c-format
msgid "error creating passphrase: %s\n"
msgstr "error creando contraseña: %s\n"
#: g10/encode.c:155 g10/encode.c:269
#, fuzzy, c-format
msgid "%s: WARNING: empty file\n"
msgstr "%s: atención: fichero vacío\n"
#: g10/encode.c:222
#, c-format
msgid "reading from '%s'\n"
msgstr "leyendo desde '%s'\n"
#: g10/encode.c:397
#, fuzzy, c-format
msgid "%s/%s encrypted for: %s\n"
msgstr "%s cifrado para: %s\n"
#: g10/export.c:114
#, fuzzy, c-format
msgid "%s: user not found: %s\n"
msgstr "%s: usuario no encontrado\n"
#: g10/export.c:123
#, c-format
msgid "certificate read problem: %s\n"
msgstr ""
#: g10/export.c:132
#, fuzzy, c-format
msgid "key %08lX: not a rfc2440 key - skipped\n"
msgstr "clave %08lX: clave secreta sin clave pública - ignorada\n"
#: g10/export.c:174
#, fuzzy
msgid "WARNING: nothing exported\n"
msgstr "ATENCIÓN: ¡Usando una clave no fiable!\n"
#: g10/getkey.c:164
msgid "too many entries in pk cache - disabled\n"
msgstr ""
#: g10/getkey.c:263
msgid "too many entries in unk cache - disabled\n"
msgstr ""
#: g10/getkey.c:989
#, c-format
msgid "using secondary key %08lX instead of primary key %08lX\n"
msgstr "usando clave secundaria %08lX en vez de clave primaria %08lX\n"
-#: g10/import.c:129 g10/trustdb.c:1166
+#: g10/import.c:129 g10/trustdb.c:1180
#, c-format
msgid "can't open file: %s\n"
msgstr "no puede abrirse el fichero: %s\n"
#: g10/import.c:145
#, c-format
msgid "skipping block of type %d\n"
msgstr "ignorando bloque de tipo %d\n"
-#: g10/import.c:152 g10/trustdb.c:1425 g10/trustdb.c:1494
+#: g10/import.c:152 g10/trustdb.c:1474 g10/trustdb.c:1543
#, c-format
msgid "%lu keys so far processed\n"
msgstr ""
-#: g10/import.c:157 g10/trustdb.c:1242
+#: g10/import.c:157 g10/trustdb.c:1256
#, c-format
msgid "read error: %s\n"
msgstr "error de lectura: %s\n"
#: g10/import.c:159
#, c-format
msgid "Total number processed: %lu\n"
msgstr ""
#: g10/import.c:161
#, c-format
msgid " w/o user IDs: %lu\n"
msgstr ""
#: g10/import.c:163
#, c-format
msgid " imported: %lu"
msgstr ""
#: g10/import.c:169
#, c-format
msgid " unchanged: %lu\n"
msgstr ""
#: g10/import.c:171
#, c-format
msgid " new user IDs: %lu\n"
msgstr ""
#: g10/import.c:173
#, c-format
msgid " new subkeys: %lu\n"
msgstr ""
#: g10/import.c:175
#, fuzzy, c-format
msgid " new signatures: %lu\n"
msgstr "clave %08lX: %d nuevas firmas\n"
#: g10/import.c:177
#, c-format
msgid " new key revocations: %lu\n"
msgstr ""
#: g10/import.c:179
#, fuzzy, c-format
msgid " secret keys read: %lu\n"
msgstr "enum_secret_keys fallido: %s\n"
#: g10/import.c:181
#, fuzzy, c-format
msgid " secret keys imported: %lu\n"
msgstr "clave %08lX: clave secreta importata\n"
#: g10/import.c:183
#, fuzzy, c-format
msgid " secret keys unchanged: %lu\n"
msgstr "enum_secret_keys fallido: %s\n"
#: g10/import.c:325 g10/import.c:517
#, c-format
msgid "key %08lX: no user id\n"
msgstr "clave %08lX: no hay id de usuario\n"
#: g10/import.c:336
#, c-format
msgid "key %08lX: no valid user ids\n"
msgstr "clave %08lX: no hay ids de usuario válidos\n"
#: g10/import.c:338
msgid "this may be caused by a missing self-signature\n"
msgstr "esto puede ser debido a la ausencia de autofirma\n"
#: g10/import.c:349 g10/import.c:585
#, c-format
msgid "key %08lX: public key not found: %s\n"
msgstr "clave %08lX: clave pública no encontrada: %s\n"
#: g10/import.c:355
msgid "no default public keyring\n"
msgstr "no hay anillo público por defecto\n"
-#: g10/import.c:359 g10/openfile.c:105 g10/sign.c:205 g10/sign.c:569
+#: g10/import.c:359 g10/openfile.c:105 g10/sign.c:205 g10/sign.c:592
#, c-format
msgid "writing to '%s'\n"
msgstr "escribiendo en '%s'\n"
#: g10/import.c:363 g10/import.c:423 g10/import.c:639
#, c-format
msgid "can't lock public keyring: %s\n"
msgstr "no puede bloquearse el anillo público: %s\n"
#: g10/import.c:366
#, c-format
msgid "can't write to keyring: %s\n"
msgstr "no puede escribirse en el anillo: %s\n"
#: g10/import.c:370
#, c-format
msgid "key %08lX: public key imported\n"
msgstr "clave %08lX: clave pública importada\n"
#: g10/import.c:383
#, c-format
msgid "key %08lX: doesn't match our copy\n"
msgstr "clave %08lX: no se corresponde con nuestra copia\n"
#: g10/import.c:396 g10/import.c:594
#, c-format
msgid "key %08lX: can't locate original keyblock: %s\n"
msgstr "clave %08lX: no puede localizarse el bloque de claves original: %s\n"
#: g10/import.c:403 g10/import.c:601
#, c-format
msgid "key %08lX: can't read original keyblock: %s\n"
msgstr "clave %08lX: no puede leerse el bloque de claves original: %s\n"
#: g10/import.c:420 g10/import.c:532 g10/import.c:636
msgid "writing keyblock\n"
msgstr "escribiendo bloque de claves\n"
#: g10/import.c:426 g10/import.c:642
#, c-format
msgid "can't write keyblock: %s\n"
msgstr "no puede escribirse el bloque de claves: %s\n"
#: g10/import.c:431
#, c-format
msgid "key %08lX: 1 new user-id\n"
msgstr "clave %08lX: 1 nuevo id de usuario\n"
#: g10/import.c:434
#, c-format
msgid "key %08lX: %d new user-ids\n"
msgstr "clave %08lX: %d nuevos ids de usuario\n"
#: g10/import.c:437
#, c-format
msgid "key %08lX: 1 new signature\n"
msgstr "clave %08lX: 1 nueva firma\n"
#: g10/import.c:440
#, c-format
msgid "key %08lX: %d new signatures\n"
msgstr "clave %08lX: %d nuevas firmas\n"
#: g10/import.c:443
#, c-format
msgid "key %08lX: 1 new subkey\n"
msgstr "clave %08lX: 1 nueva subclave\n"
#: g10/import.c:446
#, c-format
msgid "key %08lX: %d new subkeys\n"
msgstr "clave %08lX: %d nuevas subclaves\n"
#: g10/import.c:456
#, c-format
msgid "key %08lX: not changed\n"
msgstr "clave %08lX: sin cambios\n"
#: g10/import.c:535
#, c-format
msgid "can't lock secret keyring: %s\n"
msgstr "no puede bloquearse el anillo secreto: %s\n"
#: g10/import.c:538
#, c-format
msgid "can't write keyring: %s\n"
msgstr "no puede escribirse el anillo: %s\n"
#. we are ready
#: g10/import.c:541
#, c-format
msgid "key %08lX: secret key imported\n"
msgstr "clave %08lX: clave secreta importata\n"
#. we can't merge secret keys
#: g10/import.c:545
#, c-format
msgid "key %08lX: already in secret keyring\n"
msgstr "clave %08lX: ya estaba en el anillo secreto\n"
#: g10/import.c:550
#, c-format
msgid "key %08lX: secret key not found: %s\n"
msgstr "clave %08lX: clave secreta no encontrada: %s\n"
#: g10/import.c:579
#, c-format
msgid "key %08lX: no public key - can't apply revocation certificate\n"
msgstr ""
"clave %08lX: falta la clave pública - imposibile applicar el\n"
"certificado de revocación\n"
#: g10/import.c:612
#, c-format
msgid "key %08lX: invalid revocation certificate: %s - rejected\n"
msgstr "clave %08lX: certificado de revocación no válido: %s - rechazado\n"
#: g10/import.c:646
#, c-format
msgid "key %08lX: revocation certificate imported\n"
msgstr "clave %08lX: certificado de revocación importado\n"
#: g10/import.c:677
#, c-format
msgid "key %08lX: no user-id for signature\n"
msgstr "clave %08lX: no hay id de usuario para la firma\n"
#: g10/import.c:684
#, c-format
msgid "key %08lX: unsupported public key algorithm\n"
msgstr "clave %08lX: algoritmo da clave pública no soportado\n"
#: g10/import.c:685
#, c-format
msgid "key %08lX: invalid self-signature\n"
msgstr "clave %08lX: autofirma no válida\n"
#: g10/import.c:714
#, c-format
msgid "key %08lX: skipped userid '"
msgstr "clave %08lX: ignorado id de usuario '"
#: g10/import.c:737
#, c-format
msgid "key %08lX: revocation certificate at wrong place - skipped\n"
msgstr ""
"clave %08lX: certificado de revocación en sitio equivocado - ignorado\n"
#: g10/import.c:745
#, c-format
msgid "key %08lX: invalid revocation certificate: %s - skipped\n"
msgstr "clave %08lX: certificado de revocación no valido: %s - ignorado\n"
#: g10/import.c:804
#, c-format
msgid "key %08lX: revocation certificate added\n"
msgstr "clave %08lX: certificado de revocación añadido\n"
#: g10/import.c:918 g10/import.c:973
#, c-format
msgid "key %08lX: our copy has no self-signature\n"
msgstr "clave %08lX: nuestra copia no tiene autofirma\n"
#: g10/keyedit.c:81
#, c-format
msgid "%s: user not found\n"
msgstr "%s: usuario no encontrado\n"
#: g10/keyedit.c:164
msgid "[self-signature]"
msgstr "[autofirma]"
#: g10/keyedit.c:182
msgid "1 bad signature\n"
msgstr "1 firma incorrecta\n"
#: g10/keyedit.c:184
#, c-format
msgid "%d bad signatures\n"
msgstr "%d firmas incorrectas\n"
#: g10/keyedit.c:186
msgid "1 signature not checked due to a missing key\n"
msgstr "1 firma no comprobada por falta de clave\n"
#: g10/keyedit.c:188
#, c-format
msgid "%d signatures not checked due to missing keys\n"
msgstr "%d firmas no comprobadas por falta de clave\n"
#: g10/keyedit.c:190
msgid "1 signature not checked due to an error\n"
msgstr "1 firma no comprobada por causa de un error\n"
#: g10/keyedit.c:192
#, c-format
msgid "%d signatures not checked due to errors\n"
msgstr "%d firmas no comprobadas por causa de un error\n"
#: g10/keyedit.c:194
msgid "1 user id without valid self-signature detected\n"
msgstr "Detectado 1 id de usuario sin autofirma válida\n"
#: g10/keyedit.c:196
#, c-format
msgid "%d user ids without valid self-signatures detected\n"
msgstr "Detectados %d ids de usuario sin autofirma válida\n"
#: g10/keyedit.c:258
#, c-format
msgid "Already signed by key %08lX\n"
msgstr "Ya firmada por la clave %08lX\n"
#: g10/keyedit.c:266
#, c-format
msgid "Nothing to sign with key %08lX\n"
msgstr "Nada que firmar con la clave %08lX\n"
#: g10/keyedit.c:275
msgid ""
"Are you really sure that you want to sign this key\n"
"with your key: \""
msgstr ""
"¿Está realmente seguro de querer firmar esta clave\n"
"con su clave: \""
#: g10/keyedit.c:282
msgid "Really sign? "
msgstr "¿Firmar de verdad? "
#: g10/keyedit.c:303 g10/sign.c:65
#, c-format
msgid "signing failed: %s\n"
msgstr "firma fallida: %s\n"
#: g10/keyedit.c:356
msgid "This key is not protected.\n"
msgstr "Esta clave no está protegida.\n"
#: g10/keyedit.c:359
msgid "Key is protected.\n"
msgstr "La clave está protegida.\n"
#: g10/keyedit.c:376
#, c-format
msgid "Can't edit this key: %s\n"
msgstr "No puede editarse esta clave: %s\n"
#: g10/keyedit.c:381
msgid ""
"Enter the new passphrase for this secret key.\n"
"\n"
msgstr ""
"Introduzca la nueva contraseña para esta clave secreta.\n"
"\n"
#: g10/keyedit.c:393
msgid ""
"You don't want a passphrase - this is probably a *bad* idea!\n"
"\n"
msgstr ""
"No ha especificado contraseña. Esto es probablemente una *mala* idea.\n"
"\n"
#: g10/keyedit.c:396
msgid "Do you really want to do this? "
msgstr "¿Realmente quiere hacer esto? "
#: g10/keyedit.c:455
msgid "moving a key signature to the correct place\n"
msgstr ""
#: g10/keyedit.c:490
msgid "quit"
msgstr ""
#: g10/keyedit.c:490
msgid "quit this menu"
msgstr "sale de este menú"
#: g10/keyedit.c:491
msgid "q"
msgstr ""
#: g10/keyedit.c:492
msgid "save"
msgstr ""
#: g10/keyedit.c:492
msgid "save and quit"
msgstr "graba y sale"
#: g10/keyedit.c:493
msgid "help"
msgstr ""
#: g10/keyedit.c:493
msgid "show this help"
msgstr "muestra esta ayuda"
#: g10/keyedit.c:495
msgid "fpr"
msgstr ""
#: g10/keyedit.c:495
msgid "show fingerprint"
msgstr "muestra huella digital"
#: g10/keyedit.c:496
msgid "list"
msgstr ""
#: g10/keyedit.c:496
msgid "list key and user ids"
msgstr "lista clave e identificativos de usuario"
#: g10/keyedit.c:497
msgid "l"
msgstr ""
#: g10/keyedit.c:498
msgid "uid"
msgstr ""
#: g10/keyedit.c:498
msgid "select user id N"
msgstr "selecciona identificativo de usuario N"
#: g10/keyedit.c:499
msgid "key"
msgstr ""
#: g10/keyedit.c:499
msgid "select secondary key N"
msgstr "selecciona clave secundaria N"
#: g10/keyedit.c:500
msgid "check"
msgstr ""
#: g10/keyedit.c:500
msgid "list signatures"
msgstr "lista firmas"
#: g10/keyedit.c:501
msgid "c"
msgstr ""
#: g10/keyedit.c:502
msgid "sign"
msgstr ""
#: g10/keyedit.c:502
msgid "sign the key"
msgstr "firma la clave"
#: g10/keyedit.c:503
msgid "s"
msgstr ""
#: g10/keyedit.c:504
msgid "debug"
msgstr ""
#: g10/keyedit.c:505
msgid "adduid"
msgstr ""
#: g10/keyedit.c:505
msgid "add a user id"
msgstr "añade un identificativo de usuario"
#: g10/keyedit.c:506
msgid "deluid"
msgstr ""
#: g10/keyedit.c:506
msgid "delete user id"
msgstr "borra un identificativo de usuario"
#: g10/keyedit.c:507
msgid "addkey"
msgstr ""
#: g10/keyedit.c:507
msgid "add a secondary key"
msgstr "añade una clave secundaria"
#: g10/keyedit.c:508
msgid "delkey"
msgstr ""
#: g10/keyedit.c:508
msgid "delete a secondary key"
msgstr "borra una clave secundaria"
#: g10/keyedit.c:509
msgid "expire"
msgstr ""
#: g10/keyedit.c:509
msgid "change the expire date"
msgstr "cambia fecha de caducidad"
#: g10/keyedit.c:510
msgid "toggle"
msgstr ""
#: g10/keyedit.c:510
msgid "toggle between secret and public key listing"
msgstr "cambia entre lista de claves secretas y públicas"
#: g10/keyedit.c:512
msgid "t"
msgstr ""
#: g10/keyedit.c:513
msgid "pref"
msgstr ""
#: g10/keyedit.c:513
msgid "list preferences"
msgstr "muestra preferencias"
#: g10/keyedit.c:514
msgid "passwd"
msgstr ""
#: g10/keyedit.c:514
msgid "change the passphrase"
msgstr "cambia la contraseña"
#: g10/keyedit.c:515
msgid "trust"
msgstr ""
#: g10/keyedit.c:515
msgid "change the ownertrust"
msgstr "cambia valores de confianza"
#: g10/keyedit.c:534
msgid "can't do that in batchmode\n"
msgstr "imposible hacer esto en modo de proceso por lotes\n"
#. check that they match
#. FIXME: check that they both match
#: g10/keyedit.c:561
msgid "Secret key is available.\n"
msgstr "Clave secreta disponible.\n"
#: g10/keyedit.c:590
msgid "Command> "
msgstr "Comando> "
#: g10/keyedit.c:617
msgid "Need the secret key to do this.\n"
msgstr "Se necesita la clave secreta para hacer esto\n"
#: g10/keyedit.c:639
msgid "Save changes? "
msgstr "¿Grabar cambios? "
#: g10/keyedit.c:642
msgid "Quit without saving? "
msgstr "¿Salir sin grabar? "
#: g10/keyedit.c:652
#, c-format
msgid "update failed: %s\n"
msgstr "actualización fallida: %s\n"
#: g10/keyedit.c:659
#, c-format
msgid "update secret failed: %s\n"
msgstr "actualización de la clave secreta fallida: %s\n"
#: g10/keyedit.c:666
msgid "Key not changed so no update needed.\n"
msgstr "Clave sin cambios, no se necesita actualización.\n"
#: g10/keyedit.c:669 g10/keyedit.c:727
#, c-format
msgid "update of trust db failed: %s\n"
msgstr "actualización de confianza fallida: %s\n"
#: g10/keyedit.c:701
msgid "Really sign all user ids? "
msgstr "¿Firmar realmente todos los identificativos de usuario? "
#: g10/keyedit.c:702
msgid "Hint: Select the user ids to sign\n"
msgstr "Sugerencia: seleccione los identificativos de usuario a firmar\n"
#: g10/keyedit.c:738
msgid "You must select at least one user id.\n"
msgstr "Debe seleccionar por lo menos un identificativo de usuario.\n"
#: g10/keyedit.c:740
msgid "You can't delete the last user id!\n"
msgstr "¡No puede borrar el último identificativo de usuario!\n"
#: g10/keyedit.c:743
msgid "Really remove all selected user ids? "
msgstr "¿Borrar realmente todos los identificativos seleccionados? "
#: g10/keyedit.c:744
msgid "Really remove this user id? "
msgstr "¿Borrar realmente este identificativo? "
#: g10/keyedit.c:767
msgid "You must select at least one key.\n"
msgstr "Debe seleccionar por lo menos una clave.\n"
#: g10/keyedit.c:771
msgid "Do you really want to delete the selected keys? "
msgstr "¿Borrar realmente las claves seleccionadas? "
#: g10/keyedit.c:772
msgid "Do you really want to delete this key? "
msgstr "¿Borrar realmente esta clave? "
#: g10/keyedit.c:819
msgid "Invalid command (try \"help\")\n"
msgstr "Comando no válido (pruebe \"help\")\n"
#: g10/keyedit.c:1197
msgid "Please remove selections from the secret keys.\n"
msgstr "Por favor, quite la selección de las claves secretas.\n"
#: g10/keyedit.c:1203
msgid "Please select at most one secondary key.\n"
msgstr "Por favor, seleccione como máximo una clave secundaria\n"
#: g10/keyedit.c:1207
msgid "Changing exiration time for a secondary key.\n"
msgstr "Cambiando caducidad de clave secundaria.\n"
#: g10/keyedit.c:1209
msgid "Changing exiration time for the primary key.\n"
msgstr "Cambiando caducidad de clave primaria.\n"
#: g10/keyedit.c:1250
msgid "You can't change the expiration date of a v3 key\n"
msgstr ""
#: g10/keyedit.c:1266
msgid "No corresponding signature in secret ring\n"
msgstr "No hay firma correspondiente en anillo secreto\n"
#: g10/keyedit.c:1326
#, c-format
msgid "No user id with index %d\n"
msgstr "No hay ningún identificativo de usuario con el índice %d\n"
#: g10/keyedit.c:1371
#, c-format
msgid "No secondary key with index %d\n"
msgstr "No hay ninguna clave secundaria con el índice %d\n"
#: g10/mainproc.c:198
#, fuzzy
msgid "public key encrypted data: Good DEK\n"
msgstr "descifrado de la clave pública fallido: %s\n"
#: g10/mainproc.c:201
#, c-format
msgid "public key decryption failed: %s\n"
msgstr "descifrado de la clave pública fallido: %s\n"
#: g10/mainproc.c:228
#, fuzzy
msgid "decryption okay\n"
msgstr "descifrado fallido: %s\n"
#: g10/mainproc.c:231
#, c-format
msgid "decryption failed: %s\n"
msgstr "descifrado fallido: %s\n"
#: g10/mainproc.c:248
#, fuzzy
msgid "NOTE: sender requested \"for-your-eyes-only\"\n"
msgstr "nota: el remitente solicitó \"sólo-para-tus-ojos\"\n"
#: g10/mainproc.c:250
#, c-format
msgid "original file name='%.*s'\n"
msgstr ""
#: g10/mainproc.c:833
msgid "signature verification suppressed\n"
msgstr ""
#: g10/mainproc.c:839
#, c-format
msgid "Signature made %.*s using %s key ID %08lX\n"
msgstr "Firma creada %.*s usando identificativo de clave %08lX\n"
#: g10/mainproc.c:847
msgid "BAD signature from \""
msgstr "Firma INCORRECTA de \""
#: g10/mainproc.c:848
msgid "Good signature from \""
msgstr "Firma correcta de \""
#: g10/mainproc.c:861
#, c-format
msgid "Can't check signature: %s\n"
msgstr "Imposible comprobar la firma: %s\n"
#: g10/mainproc.c:934
msgid "old style (PGP 2.x) signature\n"
msgstr ""
#: g10/mainproc.c:939
msgid "invalid root packet detected in proc_tree()\n"
msgstr ""
#: g10/misc.c:88
#, fuzzy, c-format
msgid "can't disable core dumps: %s\n"
msgstr "no puede abrirse '%s': %s\n"
#: g10/misc.c:90
msgid "WARNING: Program may create a core file!\n"
msgstr ""
#: g10/misc.c:198
msgid "Experimental algorithms should not be used!\n"
msgstr ""
#: g10/misc.c:212
msgid ""
"RSA keys are deprecated; please consider creating a new key and use this key "
"in the future\n"
msgstr ""
"Las claves RSA están en desuso, considere la creación de una nueva clave "
"para futuros usos\n"
#: g10/misc.c:233
msgid "This cipher algorithm is depreciated; please use a more standard one!\n"
msgstr ""
#: g10/parse-packet.c:109
#, fuzzy, c-format
msgid "can't handle public key algorithm %d\n"
msgstr "no puede bloquearse el anillo público: %s\n"
+#: g10/parse-packet.c:801
+#, c-format
+msgid "subpacket of type %d has critical bit set\n"
+msgstr ""
+
#: g10/passphrase.c:141
msgid ""
"\n"
"You need a passphrase to unlock the secret key for\n"
"user: \""
msgstr ""
"\n"
"Necesita una contraseña para desbloquear la clave secreta\n"
"del usuario: \""
#: g10/passphrase.c:150
#, c-format
msgid "(%u-bit %s key, ID %08lX, created %s)\n"
msgstr "clave %2$s de %1$u bits, ID %3$08lX, creada el %4$s)\n"
#: g10/passphrase.c:174
#, fuzzy
msgid "Enter passphrase: "
msgstr "Introduzca contraseña: "
#: g10/passphrase.c:178
#, fuzzy
msgid "Repeat passphrase: "
msgstr "Repita contraseña: "
-#: g10/plaintext.c:102
+#: g10/plaintext.c:103
msgid "data not saved; use option \"--output\" to save it\n"
msgstr "datos no grabados; use la opción \"--output\" para grabarlos\n"
-#: g10/plaintext.c:215
+#: g10/plaintext.c:216
msgid "Please enter name of data file: "
msgstr "Introduzca el nombre del fichero de datos: "
-#: g10/plaintext.c:236
+#: g10/plaintext.c:237
msgid "reading stdin ...\n"
msgstr ""
-#: g10/plaintext.c:299
+#: g10/plaintext.c:300
#, c-format
msgid "can't open signed data '%s'\n"
msgstr "imposible abrir datos firmados '%s'\n"
#: g10/pubkey-enc.c:78
#, c-format
msgid "anonymous receiver; trying secret key %08lX ...\n"
msgstr "destinatario anónimo, probando clave secreta %08lX ...\n"
#: g10/pubkey-enc.c:84
msgid "okay, we are the anonymous receiver.\n"
msgstr "De acuerdo, somo el destinatario anónimo.\n"
#: g10/pubkey-enc.c:136
#, fuzzy
msgid "old encoding of the DEK is not supported\n"
msgstr "el algoritmo de protección %d no está soportado\n"
#: g10/pubkey-enc.c:183
#, fuzzy, c-format
msgid "NOTE: cipher algorithm %d not found in preferences\n"
msgstr "nota: algoritmo de cifrado %d no encontrado en las preferencias\n"
#: g10/seckey-cert.c:56
#, c-format
msgid "protection algorithm %d is not supported\n"
msgstr "el algoritmo de protección %d no está soportado\n"
#: g10/seckey-cert.c:169
msgid "Invalid passphrase; please try again ...\n"
msgstr "Contraseña incorrecta, inténtelo de nuevo...\n"
#: g10/seckey-cert.c:216
#, fuzzy
msgid "WARNING: Weak key detected - please change passphrase again.\n"
msgstr "Aviso: detectada clave débil - por favor cambie la contraseña.\n"
#: g10/sig-check.c:155
msgid ""
"this is a PGP generated ElGamal key which is NOT secure for signatures!\n"
msgstr ""
"¡esto es una clave ElGamal generada por PGP que NO es segura para las "
"firmas!\n"
#: g10/sig-check.c:165
msgid "public key created in future (time warp or clock problem)\n"
msgstr ""
"clave pública creada en el futuro (salto en el tiempo o problemas con el "
"reloj)\n"
#: g10/sig-check.c:170
#, fuzzy, c-format
msgid "NOTE: signature key expired %s\n"
msgstr "atención: firma de la clave caducada el %s\n"
+#: g10/sig-check.c:226
+msgid "assuming bad signature due to an unknown critical bit\n"
+msgstr ""
+
#: g10/sign.c:69
#, fuzzy, c-format
msgid "%s signature from: %s\n"
msgstr "Firma INCORRECTA de \""
-#: g10/sign.c:200 g10/sign.c:564
+#: g10/sign.c:200 g10/sign.c:587
#, fuzzy, c-format
msgid "can't create %s: %s\n"
msgstr "no puede abrirse '%s': %s\n"
#: g10/sign.c:296
msgid "signing:"
msgstr ""
#: g10/sign.c:336
#, fuzzy, c-format
msgid "WARNING: '%s' is an empty file\n"
msgstr "%s: atención: fichero vacío\n"
#: g10/tdbio.c:116 g10/tdbio.c:1413
#, fuzzy, c-format
msgid "trustdb rec %lu: lseek failed: %s\n"
msgstr "actualización de la clave secreta fallida: %s\n"
#: g10/tdbio.c:122 g10/tdbio.c:1420
#, c-format
msgid "trustdb rec %lu: write failed (n=%d): %s\n"
msgstr ""
#: g10/tdbio.c:232
msgid "trustdb transaction to large\n"
msgstr ""
#: g10/tdbio.c:402
#, fuzzy, c-format
msgid "%s: can't access: %s\n"
msgstr "%s: no puede abrirse: %s\n"
#: g10/ringedit.c:273 g10/tdbio.c:422
#, fuzzy, c-format
msgid "%s: can't create directory: %s\n"
msgstr "%s: no puede abrirse: %s\n"
#: g10/ringedit.c:279 g10/tdbio.c:425
#, c-format
msgid "%s: directory created\n"
msgstr ""
#: g10/tdbio.c:429
#, c-format
msgid "%s: directory does not exist!\n"
msgstr ""
#: g10/openfile.c:101 g10/openfile.c:165 g10/ringedit.c:1256 g10/tdbio.c:435
#, fuzzy, c-format
msgid "%s: can't create: %s\n"
msgstr "%s: no puede abrirse: %s\n"
#: g10/tdbio.c:459
#, c-format
msgid "%s: failed to create version record: %s"
msgstr ""
#: g10/tdbio.c:463
#, c-format
msgid "%s: invalid trust-db created\n"
msgstr ""
#: g10/tdbio.c:465
#, c-format
msgid "%s: trust-db created\n"
msgstr ""
#: g10/tdbio.c:506
#, c-format
msgid "%s: invalid trust-db\n"
msgstr ""
#: g10/tdbio.c:540
#, c-format
msgid "%s: failed to create hashtable: %s\n"
msgstr ""
#: g10/tdbio.c:548
#, fuzzy, c-format
msgid "%s: error updating version record: %s\n"
msgstr "%s: error comprobando la clave: %s\n"
#: g10/tdbio.c:564 g10/tdbio.c:603 g10/tdbio.c:628 g10/tdbio.c:1346
#: g10/tdbio.c:1373
#, fuzzy, c-format
msgid "%s: error reading version record: %s\n"
msgstr "%s: error comprobando la clave: %s\n"
#: g10/tdbio.c:577
#, fuzzy, c-format
msgid "%s: error writing version record: %s\n"
msgstr "%s: error comprobando la clave: %s\n"
#: g10/tdbio.c:1053
#, fuzzy, c-format
msgid "trustdb: lseek failed: %s\n"
msgstr "actualización de la clave secreta fallida: %s\n"
#: g10/tdbio.c:1061
#, fuzzy, c-format
msgid "trustdb: read failed (n=%d): %s\n"
msgstr "actualización de confianza fallida: %s\n"
#: g10/tdbio.c:1082
#, fuzzy, c-format
msgid "%s: not a trustdb file\n"
msgstr "actualización de confianza fallida: %s\n"
#: g10/tdbio.c:1098
#, c-format
msgid "%s: version record with recnum %lu\n"
msgstr ""
#: g10/tdbio.c:1103
#, fuzzy, c-format
msgid "%s: invalid file version %d\n"
msgstr "cabecera de firma clara no válida\n"
#: g10/tdbio.c:1379
#, fuzzy, c-format
msgid "%s: error reading free record: %s\n"
msgstr "%s: error comprobando la clave: %s\n"
#: g10/tdbio.c:1387
#, fuzzy, c-format
msgid "%s: error writing dir record: %s\n"
msgstr "%s: error comprobando la clave: %s\n"
#: g10/tdbio.c:1397
#, c-format
msgid "%s: failed to zero a record: %s\n"
msgstr ""
#: g10/tdbio.c:1427
#, c-format
msgid "%s: failed to append a record: %s\n"
msgstr ""
-#: g10/trustdb.c:134
+#: g10/trustdb.c:142
msgid "The trust DB is corrupted; please run \"gpgm --fix-trust-db\".\n"
msgstr ""
"La base de datos de confianza está dañada. Por favor, ejecute\n"
"\"gpgm --fix-trust-db\".\n"
-#: g10/trustdb.c:147
+#: g10/trustdb.c:155
#, c-format
msgid "trust record %lu, req type %d: read failed: %s\n"
msgstr ""
-#: g10/trustdb.c:162
+#: g10/trustdb.c:170
#, c-format
msgid "trust record %lu, type %d: write failed: %s\n"
msgstr ""
-#: g10/trustdb.c:176
+#: g10/trustdb.c:184
#, fuzzy, c-format
msgid "trust record %lu: delete failed: %s\n"
msgstr "actualización de la clave secreta fallida: %s\n"
-#: g10/trustdb.c:190
+#: g10/trustdb.c:198
#, fuzzy, c-format
msgid "trust db: sync failed: %s\n"
msgstr "actualización de confianza fallida: %s\n"
-#: g10/trustdb.c:319
+#: g10/trustdb.c:327
#, c-format
msgid "error reading dir record for LID %lu: %s\n"
msgstr ""
-#: g10/trustdb.c:326
+#: g10/trustdb.c:334
#, c-format
msgid "lid %lu: expected dir record, got type %d\n"
msgstr ""
-#: g10/trustdb.c:331
+#: g10/trustdb.c:339
#, c-format
msgid "no primary key for LID %lu\n"
msgstr ""
-#: g10/trustdb.c:336
+#: g10/trustdb.c:344
#, fuzzy, c-format
msgid "error reading primary key for LID %lu: %s\n"
msgstr "error creando contraseña: %s\n"
-#: g10/trustdb.c:412
+#: g10/trustdb.c:420
#, c-format
msgid "chained sigrec %lu has a wrong owner\n"
msgstr ""
-#: g10/trustdb.c:455
+#: g10/trustdb.c:463
#, fuzzy, c-format
msgid "'%s' is not a valid long keyID\n"
msgstr "Caracter no válido en el comentario\n"
-#: g10/trustdb.c:490
+#: g10/trustdb.c:498
#, fuzzy, c-format
msgid "key %08lX: no public key for trusted key - skipped\n"
msgstr "clave %08lX: clave secreta sin clave pública - ignorada\n"
-#: g10/trustdb.c:499 g10/trustdb.c:557
+#: g10/trustdb.c:507 g10/trustdb.c:565
#, c-format
msgid "key %08lX: can't put it into the trustdb\n"
msgstr "clave %08lX: imposible incluirla en la base de datos de confianza\n"
-#: g10/trustdb.c:504 g10/trustdb.c:563
+#: g10/trustdb.c:512 g10/trustdb.c:571
#, c-format
msgid "key %08lX: query record failed\n"
msgstr "clave %08lX: petición de registro fallida\n"
-#: g10/trustdb.c:509 g10/trustdb.c:572
+#: g10/trustdb.c:517 g10/trustdb.c:580
#, fuzzy, c-format
msgid "key %08lX: already in trusted key table\n"
msgstr "clave %08lX: ya está en la tabla secreta\n"
-#: g10/trustdb.c:512 g10/trustdb.c:575
+#: g10/trustdb.c:520 g10/trustdb.c:583
#, fuzzy, c-format
msgid "key %08lX: accepted as trusted key.\n"
msgstr "clave %08lX: aceptada como clave secreta.\n"
-#: g10/trustdb.c:528
+#: g10/trustdb.c:536
#, fuzzy, c-format
msgid "NOTE: secret key %08lX is NOT protected.\n"
msgstr "Esta clave no está protegida.\n"
-#: g10/trustdb.c:540
+#: g10/trustdb.c:548
#, c-format
msgid "key %08lX: secret key without public key - skipped\n"
msgstr "clave %08lX: clave secreta sin clave pública - ignorada\n"
-#: g10/trustdb.c:547
+#: g10/trustdb.c:555
#, c-format
msgid "key %08lX: secret and public key don't match\n"
msgstr "clave %08lX: las claves pública y secreta no se corresponden\n"
-#: g10/trustdb.c:583
+#: g10/trustdb.c:591
#, fuzzy, c-format
msgid "enumerate secret keys failed: %s\n"
msgstr "enum_secret_keys fallido: %s\n"
-#: g10/trustdb.c:766
+#: g10/trustdb.c:774
#, fuzzy, c-format
msgid "lid %lu: read dir record failed: %s\n"
msgstr "clave %08lX: inserción del registro de confianza fallida: %s\n"
-#: g10/trustdb.c:775
+#: g10/trustdb.c:783
#, fuzzy, c-format
msgid "lid %lu: read key record failed: %s\n"
msgstr "clave %08lX: inserción del registro de confianza fallida: %s\n"
-#: g10/trustdb.c:785
+#: g10/trustdb.c:793
#, fuzzy, c-format
msgid "lid %lu: read uid record failed: %s\n"
msgstr "clave %08lX: inserción del registro de confianza fallida: %s\n"
-#: g10/trustdb.c:794
+#: g10/trustdb.c:802
#, fuzzy, c-format
msgid "lid %lu: read pref record failed: %s\n"
msgstr "clave %08lX: inserción del registro de confianza fallida: %s\n"
-#: g10/trustdb.c:804
+#: g10/trustdb.c:812
#, fuzzy, c-format
msgid "lid %lu: read sig record failed: %s\n"
msgstr "clave %08lX: inserción del registro de confianza fallida: %s\n"
-#: g10/trustdb.c:999
+#: g10/trustdb.c:1013
msgid "Ooops, no keys\n"
msgstr ""
-#: g10/trustdb.c:1003
+#: g10/trustdb.c:1017
#, fuzzy
msgid "Ooops, no user ids\n"
msgstr "lista clave e identificativos de usuario"
-#: g10/trustdb.c:1074 g10/trustdb.c:1092
+#: g10/trustdb.c:1088 g10/trustdb.c:1106
#, c-format
msgid "user '%s' read problem: %s\n"
msgstr ""
-#: g10/trustdb.c:1077 g10/trustdb.c:1095
+#: g10/trustdb.c:1091 g10/trustdb.c:1109
#, c-format
msgid "user '%s' list problem: %s\n"
msgstr ""
-#: g10/trustdb.c:1085 g10/trustdb.c:1300
+#: g10/trustdb.c:1099 g10/trustdb.c:1346
#, fuzzy, c-format
msgid "user '%s' not found: %s\n"
msgstr "%s: usuario no encontrado\n"
-#: g10/trustdb.c:1087 g10/trustdb.c:1302
+#: g10/trustdb.c:1101 g10/trustdb.c:1348
#, c-format
msgid "problem finding '%s' in trustdb: %s\n"
msgstr ""
-#: g10/trustdb.c:1090
+#: g10/trustdb.c:1104
#, c-format
msgid "user '%s' not in trustdb\n"
msgstr ""
-#: g10/trustdb.c:1125
+#: g10/trustdb.c:1139
#, c-format
msgid ""
"# List of assigned trustvalues, created %s\n"
"# (Use \"gpgm --import-ownertrust\" to restore them)\n"
msgstr ""
-#: g10/trustdb.c:1131
+#: g10/trustdb.c:1145
msgid "directory record w/o primary key\n"
msgstr ""
-#: g10/trustdb.c:1138
+#: g10/trustdb.c:1152
#, fuzzy, c-format
msgid "error reading key record: %s\n"
msgstr "%s: error comprobando la clave: %s\n"
-#: g10/trustdb.c:1178
+#: g10/trustdb.c:1192
msgid "line too long\n"
msgstr ""
-#: g10/trustdb.c:1186
+#: g10/trustdb.c:1200
msgid "error: missing colon\n"
msgstr ""
-#: g10/trustdb.c:1191
+#: g10/trustdb.c:1205
#, fuzzy
msgid "error: invalid fingerprint\n"
msgstr "muestra huella digital"
-#: g10/trustdb.c:1195
+#: g10/trustdb.c:1209
#, fuzzy
msgid "error: no ownertrust value\n"
msgstr "exporta los valores de confianza"
-#: g10/trustdb.c:1209
+#: g10/trustdb.c:1223
#, c-format
msgid "LID %lu: changing trust from %u to %u\n"
msgstr ""
-#: g10/trustdb.c:1212
+#: g10/trustdb.c:1226
#, c-format
msgid "LID %lu: setting trust to %u\n"
msgstr ""
-#: g10/trustdb.c:1220
+#: g10/trustdb.c:1234
msgid "key not in trustdb, searching ring.\n"
msgstr ""
-#: g10/trustdb.c:1223
+#: g10/trustdb.c:1237
#, fuzzy, c-format
msgid "key not in ring: %s\n"
msgstr "no puede escribirse el anillo: %s\n"
-#: g10/trustdb.c:1227
+#: g10/trustdb.c:1241
msgid "Oops: key is now in trustdb???\n"
msgstr ""
#. update the ownertrust
-#: g10/trustdb.c:1232
+#: g10/trustdb.c:1246
#, fuzzy, c-format
msgid "insert trust record failed: %s\n"
msgstr "clave %08lX: inserción del registro de confianza fallida: %s\n"
#. error
-#: g10/trustdb.c:1238
+#: g10/trustdb.c:1252
#, fuzzy, c-format
msgid "error finding dir record: %s\n"
msgstr "eliminación de armadura fallida: %s\n"
-#: g10/trustdb.c:1305
+#: g10/trustdb.c:1351
#, c-format
msgid "user '%s' not in trustdb - inserting\n"
msgstr ""
-#: g10/trustdb.c:1308
+#: g10/trustdb.c:1354
#, fuzzy, c-format
msgid "failed to put '%s' into trustdb: %s\n"
msgstr "inicialización de la base de datos de confianza '%s' fallida\n"
-#: g10/trustdb.c:1355
+#: g10/trustdb.c:1404
#, c-format
msgid "%s: keyblock read problem: %s\n"
msgstr ""
-#: g10/trustdb.c:1369
+#: g10/trustdb.c:1418
#, fuzzy, c-format
msgid "%s: update failed: %s\n"
msgstr "actualización fallida: %s\n"
-#: g10/trustdb.c:1372
+#: g10/trustdb.c:1421
#, c-format
msgid "%s: updated\n"
msgstr ""
-#: g10/trustdb.c:1374
+#: g10/trustdb.c:1423
#, c-format
msgid "%s: okay\n"
msgstr ""
-#: g10/trustdb.c:1389
+#: g10/trustdb.c:1438
#, c-format
msgid "lid %lu: dir record w/o key - skipped\n"
msgstr ""
-#: g10/trustdb.c:1402
+#: g10/trustdb.c:1451
#, fuzzy, c-format
msgid "lid %lu: keyblock not found: %s\n"
msgstr "clave %08lX: clave pública no encontrada: %s\n"
-#: g10/trustdb.c:1411 g10/trustdb.c:1480
+#: g10/trustdb.c:1460 g10/trustdb.c:1529
#, fuzzy, c-format
msgid "lid %lu: update failed: %s\n"
msgstr "actualización fallida: %s\n"
-#: g10/trustdb.c:1417 g10/trustdb.c:1486
+#: g10/trustdb.c:1466 g10/trustdb.c:1535
#, c-format
msgid "lid %lu: updated\n"
msgstr ""
-#: g10/trustdb.c:1421 g10/trustdb.c:1490
+#: g10/trustdb.c:1470 g10/trustdb.c:1539
#, c-format
msgid "lid %lu: okay\n"
msgstr ""
-#: g10/trustdb.c:1428 g10/trustdb.c:1496
+#: g10/trustdb.c:1477 g10/trustdb.c:1545
#, c-format
msgid "%lu keys processed\n"
msgstr ""
-#: g10/trustdb.c:1430
+#: g10/trustdb.c:1479
#, fuzzy, c-format
msgid "\t%lu keys skipped\n"
msgstr "%s: ignorado: %s\n"
-#: g10/trustdb.c:1432 g10/trustdb.c:1498
+#: g10/trustdb.c:1481 g10/trustdb.c:1547
#, fuzzy, c-format
msgid "\t%lu keys with errors\n"
msgstr "Error de escritura"
-#: g10/trustdb.c:1434 g10/trustdb.c:1500
+#: g10/trustdb.c:1483 g10/trustdb.c:1549
#, c-format
msgid "\t%lu keys updated\n"
msgstr ""
-#: g10/trustdb.c:1464
+#: g10/trustdb.c:1513
#, fuzzy, c-format
msgid "lid ?: insert failed: %s\n"
msgstr "actualización de la clave secreta fallida: %s\n"
-#: g10/trustdb.c:1469
+#: g10/trustdb.c:1518
#, fuzzy, c-format
msgid "lid %lu: insert failed: %s\n"
msgstr "actualización de la clave secreta fallida: %s\n"
-#: g10/trustdb.c:1475
+#: g10/trustdb.c:1524
#, c-format
msgid "lid %lu: inserted\n"
msgstr ""
-#: g10/trustdb.c:1502
+#: g10/trustdb.c:1551
#, c-format
msgid "\t%lu keys inserted\n"
msgstr ""
-#: g10/trustdb.c:1505
+#: g10/trustdb.c:1554
#, fuzzy, c-format
msgid "enumerate keyblocks failed: %s\n"
msgstr "enum_secret_keys fallido: %s\n"
-#: g10/trustdb.c:1550
+#: g10/trustdb.c:1599
#, fuzzy, c-format
msgid "check_trust: search dir record failed: %s\n"
msgstr "clave %08lX: inserción del registro de confianza fallida: %s\n"
-#: g10/trustdb.c:1557
+#: g10/trustdb.c:1606
#, c-format
msgid "key %08lX: insert trust record failed: %s\n"
msgstr "clave %08lX: inserción del registro de confianza fallida: %s\n"
-#: g10/trustdb.c:1561
+#: g10/trustdb.c:1610
#, c-format
msgid "key %08lX.%lu: inserted into trustdb\n"
msgstr "clave %08lX.%lu: incluida en la base de datos de confianza\n"
-#: g10/trustdb.c:1569
+#: g10/trustdb.c:1618
#, c-format
msgid "key %08lX.%lu: created in future (time warp or clock problem)\n"
msgstr ""
"clave %08lX.%lu: creada en el futuro (salto en el tiempo o\n"
"problemas con el reloj)\n"
-#: g10/trustdb.c:1576
+#: g10/trustdb.c:1625
#, c-format
msgid "key %08lX.%lu: expired at %s\n"
msgstr "clave %08lX.%lu: caducada el %s\n"
-#: g10/trustdb.c:1584
+#: g10/trustdb.c:1633
#, c-format
msgid "key %08lX.%lu: trust check failed: %s\n"
msgstr "clave %08lX.%lu: comprobación de confianza fallida: %s\n"
-#: g10/trustdb.c:1753 g10/trustdb.c:1782 g10/trustdb.c:2521
+#: g10/trustdb.c:1820 g10/trustdb.c:1849 g10/trustdb.c:2588
msgid "WARNING: can't yet handle long pref records\n"
msgstr ""
-#: g10/trustdb.c:1804
+#: g10/trustdb.c:1871
#, fuzzy, c-format
msgid "get_dir_record: search_record failed: %s\n"
msgstr "actualización de la clave secreta fallida: %s\n"
-#: g10/trustdb.c:1867
+#: g10/trustdb.c:1934
#, c-format
msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but marked as checked\n"
msgstr ""
-#: g10/trustdb.c:1871
+#: g10/trustdb.c:1938
#, c-format
msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but not marked\n"
msgstr ""
#. we need the dir record
-#: g10/trustdb.c:1878
+#: g10/trustdb.c:1945
#, c-format
msgid "sig rec %lu[%d] in hintlist of %lu does not point to a dir record\n"
msgstr ""
-#: g10/trustdb.c:1884
+#: g10/trustdb.c:1951
#, c-format
msgid "lid %lu: no primary key\n"
msgstr ""
-#: g10/trustdb.c:1917
+#: g10/trustdb.c:1984
#, c-format
msgid "lid %lu: user id not found in keyblock\n"
msgstr ""
-#: g10/trustdb.c:1921
+#: g10/trustdb.c:1988
#, fuzzy, c-format
msgid "lid %lu: user id without signature\n"
msgstr "clave %08lX: no hay id de usuario para la firma\n"
-#: g10/trustdb.c:1928
+#: g10/trustdb.c:1995
#, c-format
msgid "lid %lu: self-signature in hintlist\n"
msgstr ""
-#: g10/trustdb.c:1939 g10/trustdb.c:2658 g10/trustdb.c:2742
+#: g10/trustdb.c:2006 g10/trustdb.c:2725 g10/trustdb.c:2809
#, fuzzy
msgid "Valid certificate revocation"
msgstr "Certificado incorrecto"
-#: g10/trustdb.c:1940 g10/trustdb.c:2659 g10/trustdb.c:2743
+#: g10/trustdb.c:2007 g10/trustdb.c:2726 g10/trustdb.c:2810
#, fuzzy
msgid "Good certificate"
msgstr "Certificado incorrecto"
-#: g10/trustdb.c:1949
+#: g10/trustdb.c:2016
msgid "very strange: no public key\n"
msgstr ""
-#: g10/trustdb.c:1997
+#: g10/trustdb.c:2064
#, c-format
msgid "hintlist %lu[%d] of %lu does not point to a dir record\n"
msgstr ""
-#: g10/trustdb.c:2003
+#: g10/trustdb.c:2070
#, c-format
msgid "lid %lu does not have a key\n"
msgstr ""
-#: g10/trustdb.c:2013
+#: g10/trustdb.c:2080
#, c-format
msgid "lid %lu: can't get keyblock: %s\n"
msgstr ""
-#: g10/trustdb.c:2070 g10/trustdb.c:2984
+#: g10/trustdb.c:2137 g10/trustdb.c:3051
#, fuzzy, c-format
msgid "tdbio_search_dir failed: %s\n"
msgstr "eliminación de armadura fallida: %s\n"
-#: g10/trustdb.c:2223
+#: g10/trustdb.c:2290
#, fuzzy, c-format
msgid "key %08lX.%lu: Good subkey binding\n"
msgstr "clave %08lX: no hay id de usuario\n"
-#: g10/trustdb.c:2229 g10/trustdb.c:2271
+#: g10/trustdb.c:2296 g10/trustdb.c:2338
#, fuzzy, c-format
msgid "key %08lX.%lu: Invalid subkey binding: %s\n"
msgstr "clave %08lX: no hay ids de usuario válidos\n"
-#: g10/trustdb.c:2244
+#: g10/trustdb.c:2311
#, fuzzy, c-format
msgid "key %08lX.%lu: Valid key revocation\n"
msgstr "clave %08lX.%lu: caducada el %s\n"
-#: g10/trustdb.c:2250
+#: g10/trustdb.c:2317
#, fuzzy, c-format
msgid "key %08lX.%lu: Invalid key revocation: %s\n"
msgstr "clave %08lX: clave pública no encontrada: %s\n"
-#: g10/trustdb.c:2265
+#: g10/trustdb.c:2332
#, fuzzy, c-format
msgid "key %08lX.%lu: Valid subkey revocation\n"
msgstr "clave %08lX: no hay ids de usuario válidos\n"
-#: g10/trustdb.c:2365
+#: g10/trustdb.c:2432
#, fuzzy
msgid "Good self-signature"
msgstr "[autofirma]"
-#: g10/trustdb.c:2376
+#: g10/trustdb.c:2443
#, fuzzy
msgid "Invalid self-signature"
msgstr "clave %08lX: autofirma no válida\n"
-#: g10/trustdb.c:2386
+#: g10/trustdb.c:2453
msgid "Valid user ID revocation skipped due to a newer self signature\n"
msgstr ""
-#: g10/trustdb.c:2393
+#: g10/trustdb.c:2460
#, fuzzy
msgid "Valid user ID revocation\n"
msgstr "Elección no válida.\n"
-#: g10/trustdb.c:2400
+#: g10/trustdb.c:2467
#, fuzzy
msgid "Invalid user ID revocation"
msgstr "Elección no válida.\n"
-#: g10/trustdb.c:2484
+#: g10/trustdb.c:2551
#, fuzzy
msgid "Too many preferences"
msgstr "muestra preferencias"
-#: g10/trustdb.c:2498
+#: g10/trustdb.c:2565
msgid "Too many preference items"
msgstr ""
-#: g10/trustdb.c:2637
+#: g10/trustdb.c:2704
msgid "Duplicated certificate - deleted"
msgstr ""
-#: g10/trustdb.c:2670
+#: g10/trustdb.c:2737
#, fuzzy
msgid "Hmmm, public key lost?"
msgstr "Clave pública incorrecta"
-#: g10/trustdb.c:2680 g10/trustdb.c:2763
+#: g10/trustdb.c:2747 g10/trustdb.c:2830
#, fuzzy
msgid "Invalid certificate revocation"
msgstr "Certificado incorrecto"
-#: g10/trustdb.c:2681 g10/trustdb.c:2764
+#: g10/trustdb.c:2748 g10/trustdb.c:2831
#, fuzzy
msgid "Invalid certificate"
msgstr "Certificado incorrecto"
-#: g10/trustdb.c:2696
+#: g10/trustdb.c:2763
#, c-format
msgid "uid %08lX.%lu/%02X%02X: has shadow dir %lu but is not yet marked.\n"
msgstr ""
-#: g10/trustdb.c:2710
+#: g10/trustdb.c:2777
#, c-format
msgid "sig record %lu[%d] points to wrong record.\n"
msgstr ""
#. that should never happen
-#: g10/trustdb.c:2954
+#: g10/trustdb.c:3021
#, fuzzy, c-format
msgid "insert_trust_record: keyblock not found: %s\n"
msgstr "clave %08lX: clave secreta no encontrada: %s\n"
-#: g10/trustdb.c:2972
+#: g10/trustdb.c:3039
msgid "did not use primary key for insert_trust_record()\n"
msgstr ""
#: g10/ringedit.c:293
#, fuzzy, c-format
msgid "%s: can't create keyring: %s\n"
msgstr "no puede escribirse el anillo: %s\n"
#: g10/ringedit.c:299 g10/ringedit.c:1264
#, c-format
msgid "%s: keyring created\n"
msgstr ""
#: g10/ringedit.c:1449
msgid "WARNING: 2 files with confidential information exists.\n"
msgstr ""
#: g10/ringedit.c:1450
#, c-format
msgid "%s is the unchanged one\n"
msgstr ""
#: g10/ringedit.c:1451
#, c-format
msgid "%s is the new one\n"
msgstr ""
#: g10/ringedit.c:1452
msgid "Please fix this possible security flaw\n"
msgstr ""
#: g10/skclist.c:94
#, fuzzy, c-format
msgid "skipped '%s': %s\n"
msgstr "%s: ignorado: %s\n"
#: g10/skclist.c:100
#, fuzzy, c-format
msgid ""
"skipped '%s': this is a PGP generated ElGamal key which is not secure for "
"signatures!\n"
msgstr ""
"¡esto es una clave ElGamal generada por PGP que NO es segura para las "
"firmas!\n"
#. do not overwrite
#: g10/openfile.c:58
#, c-format
msgid "File '%s' exists. "
msgstr "El fichero '%s' ya existe. "
#: g10/openfile.c:60
msgid "Overwrite (y/N)? "
msgstr "¿Sobreescribir (s/N)? "
#: g10/openfile.c:85
#, fuzzy
msgid "writing to stdout\n"
msgstr "escribiendo en '%s'\n"
#: g10/openfile.c:134
#, fuzzy, c-format
msgid "assuming signed data in '%s'\n"
msgstr "imposible abrir datos firmados '%s'\n"
#: g10/openfile.c:181
#, c-format
msgid "%s: new options file created\n"
msgstr ""
#: g10/encr-data.c:59
#, fuzzy, c-format
msgid "%s encrypted data\n"
msgstr "cifra datos"
#: g10/encr-data.c:61
#, c-format
msgid "encrypted with unknown algorithm %d\n"
msgstr ""
#: g10/encr-data.c:74
#, fuzzy
msgid ""
"WARNING: Message was encrypted with a weak key in the symmetric cipher.\n"
msgstr ""
"Atención: mensaje cifrado con una clave débil en el cifrado simétrico.\n"
#: g10/seskey.c:52
msgid "weak key created - retrying\n"
msgstr "creada clave débil - reintentando\n"
#: g10/seskey.c:57
#, c-format
msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n"
msgstr ""
"¡imposible evitar clave débil para cifrado simétrico después de %d "
"intentos!\n"
#. begin of list
-#: g10/helptext.c:45
+#: g10/helptext.c:48
msgid "edit_ownertrust.value"
msgstr ""
-#: g10/helptext.c:51
+#: g10/helptext.c:54
msgid "revoked_key.override"
msgstr ""
-#: g10/helptext.c:55
+#: g10/helptext.c:58
msgid "untrusted_key.override"
msgstr ""
-#: g10/helptext.c:59
+#: g10/helptext.c:62
msgid "pklist.user_id.enter"
msgstr ""
-#: g10/helptext.c:63
+#: g10/helptext.c:66
msgid "keygen.algo"
msgstr ""
-#: g10/helptext.c:79
+#: g10/helptext.c:82
msgid "keygen.algo.elg_se"
msgstr ""
-#: g10/helptext.c:86
+#: g10/helptext.c:89
msgid "keygen.size"
msgstr ""
-#: g10/helptext.c:90
+#: g10/helptext.c:93
msgid "keygen.size.huge.okay"
msgstr ""
-#: g10/helptext.c:95
+#: g10/helptext.c:98
msgid "keygen.size.large.okay"
msgstr ""
-#: g10/helptext.c:100
+#: g10/helptext.c:103
msgid "keygen.valid"
msgstr ""
-#: g10/helptext.c:104
+#: g10/helptext.c:107
msgid "keygen.valid.okay"
msgstr ""
-#: g10/helptext.c:109
+#: g10/helptext.c:112
msgid "keygen.name"
msgstr ""
-#: g10/helptext.c:114
+#: g10/helptext.c:117
msgid "keygen.email"
msgstr ""
-#: g10/helptext.c:118
+#: g10/helptext.c:121
msgid "keygen.comment"
msgstr ""
-#: g10/helptext.c:123
+#: g10/helptext.c:126
msgid "keygen.userid.cmd"
msgstr ""
-#: g10/helptext.c:132
+#: g10/helptext.c:135
msgid "keygen.sub.okay"
msgstr ""
-#: g10/helptext.c:136
+#: g10/helptext.c:139
msgid "sign_uid.okay"
msgstr ""
-#: g10/helptext.c:141
+#: g10/helptext.c:144
msgid "change_passwd.empty.okay"
msgstr ""
-#: g10/helptext.c:146
+#: g10/helptext.c:149
msgid "keyedit.cmd"
msgstr ""
-#: g10/helptext.c:150
+#: g10/helptext.c:153
msgid "keyedit.save.okay"
msgstr ""
-#: g10/helptext.c:155
+#: g10/helptext.c:158
msgid "keyedit.cancel.okay"
msgstr ""
-#: g10/helptext.c:159
+#: g10/helptext.c:162
msgid "keyedit.sign_all.okay"
msgstr ""
-#: g10/helptext.c:163
+#: g10/helptext.c:166
msgid "keyedit.remove.uid.okay"
msgstr ""
-#: g10/helptext.c:168
+#: g10/helptext.c:171
msgid "keyedit.remove.subkey.okay"
msgstr ""
-#: g10/helptext.c:172
+#: g10/helptext.c:175
msgid "passphrase.enter"
msgstr ""
-#: g10/helptext.c:179
+#: g10/helptext.c:182
msgid "passphrase.repeat"
msgstr ""
-#: g10/helptext.c:183
+#: g10/helptext.c:186
msgid "detached_signature.filename"
msgstr ""
-#: g10/helptext.c:187
+#: g10/helptext.c:190
msgid "openfile.overwrite.okay"
msgstr ""
-#: g10/helptext.c:201
+#: g10/helptext.c:204
msgid "No help available"
msgstr "Ayuda no disponible"
-#: g10/helptext.c:213
+#: g10/helptext.c:216
#, c-format
msgid "No help available for '%s'"
msgstr "Ayuda no disponible para '%s'"
#~ msgid "You will see a list of signators etc. here\n"
#~ msgstr "Aquí se verá una lista de firmantes, etc.\n"
#~ msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: good signature (3)\n"
#~ msgstr "clave %08lX.%lu, uid %02X%02X, firma %08lX: firma correcta (3)\n"
#~ msgid ""
#~ "key %08lX.%lu, uid %02X%02X, sig %08lX: very strange: no public key\n"
#~ msgstr ""
#~ "clave %08lX.%lu, uid %02X%02X, firma %08lX: extraño, no hay clave pública\n"
#~ msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: invalid signature: %s\n"
#~ msgstr "clave %08lX.%lu, uid %02X%02X, firma %08lX: firma incorrecta: %s\n"
#~ msgid "key %08lX.%lu, uid %02X%02X: good self-signature\n"
#~ msgstr "clave %08lX.%lu, uid %02X%02X: autofirma correcta\n"
#~ msgid ""
#~ "key %08lX.%lu, uid %02X%02X, sig %08lX: duplicated signature - deleted\n"
#~ msgstr ""
#~ "clave %08lX.%lu, uid %02X%02X, firma %08lX: firma duplicada - borrada\n"
#~ msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: good signature (1)\n"
#~ msgstr "clave %08lX.%lu, uid %02X%02X, firma %08lX: firma correcta (1)\n"
#~ msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: weird: no public key\n"
#~ msgstr ""
#~ "clave %08lX.%lu, uid %02X%02X, firma %08lX: raro, no hay clave pública\n"
#~ msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: good signature (2)\n"
#~ msgstr "clave %08lX.%lu, uid %02X%02X, firma %08lX: firma correcta (2)\n"
#~ msgid "key %08lX.%lu, uid %02X%02X, sig %08lX: no public key\n"
#~ msgstr "clave %08lX.%lu, uid %02X%02X, firma %08lX: no hay clave pública\n"
diff --git a/po/fr.po b/po/fr.po
index dbc8e415b..22914c203 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -1,3123 +1,3127 @@
# GnuPG french translation
# Copyright (C) 1998 Free Software Foundation, Inc.
# Gaël Quéri <gqueri@mail.dotcom.fr>, 1998.
#
msgid ""
msgstr ""
"Project-Id-Version: gnupg 0.4.5a\n"
-"POT-Creation-Date: 1998-12-15 00:29+0100\n"
+"POT-Creation-Date: 1998-12-17 18:30+0100\n"
"PO-Revision-Date: 1998-12-15 00:35+01:00\n"
"Last-Translator: Gaël Quéri <gqueri@mail.dotcom.fr>\n"
"Language-Team: French <fr@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ISO-8859-1\n"
"Content-Transfer-Encoding: 8-bit\n"
#: util/secmem.c:77
msgid "Warning: using insecure memory!\n"
msgstr "Attention : utilisation de la mémoire non sûre !\n"
#: util/miscutil.c:143
msgid "yes"
msgstr "oui"
#: util/miscutil.c:144
msgid "yY"
msgstr "oO"
#: util/errors.c:54
msgid "General error"
msgstr "Erreur générale"
#: util/errors.c:55
msgid "Unknown packet type"
msgstr "Type de paquet inconnu"
#: util/errors.c:56
msgid "Unknown version"
msgstr "Version inconnue"
#: util/errors.c:57
msgid "Unknown pubkey algorithm"
msgstr "Algorithme de clé publique inconnu"
#: util/errors.c:58
msgid "Unknown digest algorithm"
msgstr "Algorithme de hachage inconnu"
#: util/errors.c:59
msgid "Bad public key"
msgstr "Mauvaise clé publique"
#: util/errors.c:60
msgid "Bad secret key"
msgstr "Mauvaise clé secrète"
#: util/errors.c:61
msgid "Bad signature"
msgstr "Mauvaise signature"
#: util/errors.c:62
msgid "Checksum error"
msgstr "Erreur de checksum"
#: util/errors.c:63
msgid "Bad passphrase"
msgstr "Mauvais mot de passe"
#: util/errors.c:64
msgid "Public key not found"
msgstr "Clé publique non trouvée"
#: util/errors.c:65
msgid "Unknown cipher algorithm"
msgstr "Algorithme de chiffrement inconnu"
#: util/errors.c:66
msgid "Can't open the keyring"
msgstr "Ne peut ouvrir le porte-clés"
#: util/errors.c:67
msgid "Invalid packet"
msgstr "Paquet invalide"
#: util/errors.c:68
msgid "Invalid armor"
msgstr "Armure invalide"
#: util/errors.c:69
msgid "No such user id"
msgstr "Pas de tel utilisateur"
#: util/errors.c:70
msgid "Secret key not available"
msgstr "La clé secrète n'est pas disponible"
#: util/errors.c:71
msgid "Wrong secret key used"
msgstr "Mauvaise clé secrète utilisée"
#: util/errors.c:72
msgid "Not supported"
msgstr "Non supporté"
#: util/errors.c:73
msgid "Bad key"
msgstr "Mauvaise clé"
#: util/errors.c:74
msgid "File read error"
msgstr "Erreur de lecture"
#: util/errors.c:75
msgid "File write error"
msgstr "Erreur d'écriture"
#: util/errors.c:76
msgid "Unknown compress algorithm"
msgstr "Algorithme de compression inconnu"
#: util/errors.c:77
msgid "File open error"
msgstr "Erreur d'ouverture de fichier"
#: util/errors.c:78
msgid "File create error"
msgstr "Erreur de création de fichier"
#: util/errors.c:79
msgid "Invalid passphrase"
msgstr "Mot de passe invalide"
#: util/errors.c:80
msgid "Unimplemented pubkey algorithm"
msgstr "Algorithme de clé publique non implémenté"
#: util/errors.c:81
msgid "Unimplemented cipher algorithm"
msgstr "Algorithme de chiffrement non implémenté"
#: util/errors.c:82
msgid "Unknown signature class"
msgstr "Classe de signature inconnue"
#: util/errors.c:83
msgid "Trust database error"
msgstr "Erreur dans la base de confiance"
#: util/errors.c:84
msgid "Bad MPI"
msgstr "Mauvais entier en précision multiple"
#: util/errors.c:85
msgid "Resource limit"
msgstr "Limite de ressources"
#: util/errors.c:86
msgid "Invalid keyring"
msgstr "Porte-clés invalide"
#: util/errors.c:87
msgid "Bad certificate"
msgstr "Mauvais certificat"
#: util/errors.c:88
msgid "Malformed user id"
msgstr "Nom d'utilisateur malformé"
#: util/errors.c:89
msgid "File close error"
msgstr "Erreur de fermeture de fichier"
#: util/errors.c:90
msgid "File rename error"
msgstr "Erreur pendant le changement de nom du fichier"
#: util/errors.c:91
msgid "File delete error"
msgstr "Erreur pendant la suppression du fichier"
#: util/errors.c:92
msgid "Unexpected data"
msgstr "Données inattendues"
#: util/errors.c:93
msgid "Timestamp conflict"
msgstr "Conflit de dates"
#: util/errors.c:94
msgid "Unusable pubkey algorithm"
msgstr "Algorithme de clés publiques inutilisable"
#: util/errors.c:95
msgid "File exists"
msgstr "Le fichier existe"
#: util/errors.c:96
msgid "Weak key"
msgstr "Mauvaise clé"
#: util/logger.c:178
#, c-format
msgid "... this is a bug (%s:%d:%s)\n"
msgstr "... c'est un bug (%s:%d:%s)\n"
#: util/logger.c:184
#, c-format
msgid "you found a bug ... (%s:%d)\n"
msgstr "vous avez trouvé un bug ... (%s:%d)\n"
#: cipher/random.c:406
msgid "WARNING: using insecure random number generator!!\n"
msgstr ""
"ATTENTION : utilisation d'un générateur de nombres aléatoires peu sûr !!\n"
#: cipher/random.c:407
msgid ""
"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"
msgstr ""
"Le générateur de nombres aléatoires n'est qu'un artifice visant à exécuter\n"
"GnuPG - ce n'est en aucune manière un générateur (RNG) fort!\n"
"\n"
"N'UTILISEZ PAS LES DONNÉES GÉNÉRÉES PAR CE PROGRAMME!!\n"
"\n"
#: cipher/rndlinux.c:118
#, c-format
msgid ""
"\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"
msgstr ""
"\n"
"Il n'y a pas assez d'octets aléatoires disponibles. Faites autre chose\n"
"pour que l'OS puisse amasser plus d'entropie ! (il faut %d octets de plus)\n"
-#: g10/g10.c:159
+#: g10/g10.c:160
msgid ""
"@Commands:\n"
" "
msgstr ""
"@Commandes:\n"
" "
-#: g10/g10.c:162
+#: g10/g10.c:163
msgid "|[file]|make a signature"
msgstr "|[fichier]|faire une signature"
-#: g10/g10.c:163
+#: g10/g10.c:164
msgid "|[file]|make a clear text signature"
msgstr "|[fichier]|faire une signature en texte clair"
-#: g10/g10.c:164
+#: g10/g10.c:165
msgid "make a detached signature"
msgstr "faire une signature détachée"
-#: g10/g10.c:165
+#: g10/g10.c:166
msgid "encrypt data"
msgstr "chiffrer les données"
-#: g10/g10.c:166
+#: g10/g10.c:167
msgid "encryption only with symmetric cipher"
msgstr "chiffrement symétrique seulement"
-#: g10/g10.c:167
+#: g10/g10.c:168
msgid "store only"
msgstr "pas d'action"
-#: g10/g10.c:168
+#: g10/g10.c:169
msgid "decrypt data (default)"
msgstr "déchiffrer les données (défaut)"
-#: g10/g10.c:169
+#: g10/g10.c:170
msgid "verify a signature"
msgstr "vérifier une signature"
-#: g10/g10.c:171
+#: g10/g10.c:172
msgid "list keys"
msgstr "lister les clés"
-#: g10/g10.c:172
+#: g10/g10.c:173
msgid "list keys and signatures"
msgstr "lister les clés et les signatures"
-#: g10/g10.c:173
+#: g10/g10.c:174
msgid "check key signatures"
msgstr "vérifier les signatures des clés"
-#: g10/g10.c:174
+#: g10/g10.c:175
msgid "list keys and fingerprints"
msgstr "lister les clés et les empreintes"
-#: g10/g10.c:175
+#: g10/g10.c:176
msgid "list secret keys"
msgstr "lister les clés secrètes"
-#: g10/g10.c:177
+#: g10/g10.c:178
msgid "generate a new key pair"
msgstr "générer une nouvelle paire de clés"
-#: g10/g10.c:179
+#: g10/g10.c:180
msgid "remove key from the public keyring"
msgstr "enlever la clé du porte-clés public"
-#: g10/g10.c:181
+#: g10/g10.c:182
msgid "sign or edit a key"
msgstr "signer ou éditer une clé"
-#: g10/g10.c:182
+#: g10/g10.c:183
msgid "generate a revocation certificate"
msgstr "générer un certificat de révocation"
-#: g10/g10.c:184
+#: g10/g10.c:185
msgid "export keys"
msgstr "exporter les clés"
-#: g10/g10.c:187
+#: g10/g10.c:188
msgid "import/merge keys"
msgstr "importer/fusionner les clés"
-#: g10/g10.c:189
+#: g10/g10.c:190
msgid "list only the sequence of packets"
msgstr "ne lister que les paquets"
-#: g10/g10.c:192
+#: g10/g10.c:193
msgid "export the ownertrust values"
msgstr "exporter les indices de confiance"
-#: g10/g10.c:194
+#: g10/g10.c:195
msgid "import ownertrust values"
msgstr "importer les indices de confiance"
#
-#: g10/g10.c:196
+#: g10/g10.c:197
msgid "|[NAMES]|update the trust database"
msgstr "|[NOMS]|mettre la base de confiance à jour"
-#: g10/g10.c:198
+#: g10/g10.c:199
msgid "|[NAMES]|check the trust database"
msgstr "|[NOMS]|vérifier la base de confiance"
-#: g10/g10.c:199
+#: g10/g10.c:200
msgid "fix a corrupted trust database"
msgstr "réparer une base de confiance corrompue"
-#: g10/g10.c:200
+#: g10/g10.c:201
msgid "De-Armor a file or stdin"
msgstr "Enlever l'armure d'un fichier ou de stdin"
-#: g10/g10.c:201
+#: g10/g10.c:202
msgid "En-Armor a file or stdin"
msgstr "Mettre une armure à un fichier ou à stdin"
-#: g10/g10.c:202
+#: g10/g10.c:203
msgid "|algo [files]|print message digests"
msgstr "|alg. [fich.]|indiquer les fonctions de hachage"
-#: g10/g10.c:203
+#: g10/g10.c:204
msgid "print all message digests"
msgstr "écrire toutes les fonctions de hachage"
-#: g10/g10.c:210
+#: g10/g10.c:211
msgid ""
"@\n"
"Options:\n"
" "
msgstr ""
"@\n"
"Options:\n"
" "
-#: g10/g10.c:212
+#: g10/g10.c:213
msgid "create ascii armored output"
msgstr "créer une sortie ascii armurée"
-#: g10/g10.c:214
+#: g10/g10.c:215
msgid "use this user-id to sign or decrypt"
msgstr "utiliser ce nom pour signer ou déchiffrer"
-#: g10/g10.c:215
+#: g10/g10.c:216
msgid "use this user-id for encryption"
msgstr "utiliser ce nom d'utilisateur pour chiffrer"
-#: g10/g10.c:216
+#: g10/g10.c:217
msgid "|N|set compress level N (0 disables)"
msgstr "|N|niveau de compression N (0 désactive)"
-#: g10/g10.c:218
+#: g10/g10.c:219
msgid "use canonical text mode"
msgstr "utiliser le mode de texte canonique"
-#: g10/g10.c:220
+#: g10/g10.c:221
msgid "use as output file"
msgstr "utiliser comme fichier de sortie"
-#: g10/g10.c:221
+#: g10/g10.c:222
msgid "verbose"
msgstr "bavard"
-#: g10/g10.c:222
+#: g10/g10.c:223
msgid "be somewhat more quiet"
msgstr "devenir beaucoup plus silencieux"
#
-#: g10/g10.c:223
+#: g10/g10.c:224
msgid "force v3 signatures"
msgstr "forcer les signatures en v3"
#. { oDryRun, "dry-run", 0, N_("do not make any changes") },
-#: g10/g10.c:225
+#: g10/g10.c:226
msgid "batch mode: never ask"
msgstr "mode automatique : ne jamais rien demander"
-#: g10/g10.c:226
+#: g10/g10.c:227
msgid "assume yes on most questions"
msgstr "répondre oui à la plupart des questions"
-#: g10/g10.c:227
+#: g10/g10.c:228
msgid "assume no on most questions"
msgstr "répondre non à la plupart des questions"
-#: g10/g10.c:228
+#: g10/g10.c:229
msgid "add this keyring to the list of keyrings"
msgstr "ajouter ce porte-clés à la liste des porte-clés"
-#: g10/g10.c:229
+#: g10/g10.c:230
msgid "add this secret keyring to the list"
msgstr "ajouter ce porte-clés secret à la liste"
-#: g10/g10.c:230
+#: g10/g10.c:231
msgid "|NAME|use NAME as default secret key"
msgstr "|NOM|utiliser NOM comme clé secrète par défaut"
-#: g10/g10.c:231
+#: g10/g10.c:232
msgid "|NAME|set terminal charset to NAME"
msgstr "|NOM|le terminal utilise la table de caractères NOM"
-#: g10/g10.c:232
+#: g10/g10.c:233
msgid "read options from file"
msgstr "lire les options du fichier"
-#: g10/g10.c:234
+#: g10/g10.c:235
msgid "set debugging flags"
msgstr "choisir les attributs de déboguage"
-#: g10/g10.c:235
+#: g10/g10.c:236
msgid "enable full debugging"
msgstr "permettre un déboguage complet"
-#: g10/g10.c:236
+#: g10/g10.c:237
msgid "|FD|write status info to this FD"
msgstr "|FD|écrire l'état sur ce descripteur"
-#: g10/g10.c:237
+#: g10/g10.c:238
msgid "do not write comment packets"
msgstr "ne pas écrire de paquets de commentaire"
-#: g10/g10.c:238
+#: g10/g10.c:239
msgid "(default is 1)"
msgstr "(1 par défaut)"
-#: g10/g10.c:239
+#: g10/g10.c:240
msgid "(default is 3)"
msgstr "(3 par défaut)"
-#: g10/g10.c:241
+#: g10/g10.c:242
msgid "|KEYID|ulimately trust this key"
msgstr "|IDCLE|donner une confiance totale à cette clé"
-#: g10/g10.c:242
+#: g10/g10.c:243
msgid "|FILE|load extension module FILE"
msgstr "|FICH|charger le module d'extension FICH"
-#: g10/g10.c:243
+#: g10/g10.c:244
msgid "emulate the mode described in RFC1991"
msgstr "imiter le mode décrit dans la RFC1991"
# FIXMOI : faudra trouver mieux ...
-#: g10/g10.c:244
+#: g10/g10.c:245
msgid "|N|use passphrase mode N"
msgstr "|N|utiliser le mode de mots de passe N"
-#: g10/g10.c:246
+#: g10/g10.c:247
msgid "|NAME|use message digest algorithm NAME for passphrases"
msgstr "|NOM|utiliser le hachage NOM pour les mots de passe"
-#: g10/g10.c:248
+#: g10/g10.c:249
msgid "|NAME|use cipher algorithm NAME for passphrases"
msgstr "|NOM|utiliser le chiffrement NOM pour les mots de passe"
-#: g10/g10.c:250
+#: g10/g10.c:251
msgid "|NAME|use cipher algorithm NAME"
msgstr "|NOM|utiliser l'algorithme de chiffrement NOM"
-#: g10/g10.c:251
+#: g10/g10.c:252
msgid "|NAME|use message digest algorithm NAME"
msgstr "|NOM|utiliser la fonction de hachage NOM"
-#: g10/g10.c:252
+#: g10/g10.c:253
msgid "|N|use compress algorithm N"
msgstr "|N|utiliser l'algorithme de compression N"
-#: g10/g10.c:253
+#: g10/g10.c:254
msgid "throw keyid field of encrypted packets"
msgstr "supprimer l'identification des paquets chiffrés"
-#: g10/g10.c:261
+#: g10/g10.c:262
msgid ""
"@\n"
"Examples:\n"
"\n"
" -se -r Bob [file] sign and encrypt for user Bob\n"
" --clearsign [file] make a clear text signature\n"
" --detach-sign [file] make a detached signature\n"
" --list-keys [names] show keys\n"
" --fingerprint [names] show fingerprints\n"
msgstr ""
"@\n"
"Exemples:\n"
"\n"
" -se -r Alice [fichier] signer et crypter pour l'utilisateur Alice\n"
" --clearsign [fichier] faire une signature en texte clair\n"
" --detach-sign [fichier] faire une signature détachée\n"
" --list-keys [utilisateur] montrer les clés\n"
" --fingerprint [utilisateur] montrer les empreintes\n"
-#: g10/g10.c:339
+#: g10/g10.c:341
msgid "Please report bugs to <gnupg-bugs@gnu.org>.\n"
msgstr "Rapporter toutes anomalies à <gnupg-bugs@gnu.org>.\n"
-#: g10/g10.c:344
+#: g10/g10.c:346
msgid "Usage: gpgm [options] [files] (-h for help)"
msgstr "Utilisation: gpgm [options] [fichiers] (-h pour l'aide)"
-#: g10/g10.c:346
+#: g10/g10.c:348
msgid "Usage: gpg [options] [files] (-h for help)"
msgstr "Utilisation: gpg [options] [fichiers] (-h pour l'aide)"
#
-#: g10/g10.c:351
+#: g10/g10.c:353
msgid ""
"Syntax: gpgm [options] [files]\n"
"GnuPG maintenance utility\n"
msgstr ""
"Syntaxe: gpgm [options] [fichiers]\n"
"utilitaire de maitenance de GnuPG\n"
-#: g10/g10.c:354
+#: g10/g10.c:356
msgid ""
"Syntax: gpg [options] [files]\n"
"sign, check, encrypt or decrypt\n"
"default operation depends on the input data\n"
msgstr ""
"Syntaxe: gpg [options] [fichiers]\n"
"signer, vérifier, crypter ou décrypter\n"
"l'opération par défaut dépend des données entrées\n"
-#: g10/g10.c:360
+#: g10/g10.c:362
msgid ""
"\n"
"Supported algorithms:\n"
msgstr ""
"\n"
"Algorithmes supportés:\n"
-#: g10/g10.c:435
+#: g10/g10.c:437
msgid "usage: gpgm [options] "
msgstr "utilisation: gpgm [options] "
-#: g10/g10.c:437
+#: g10/g10.c:439
msgid "usage: gpg [options] "
msgstr "utilisation: gpg [options] "
-#: g10/g10.c:478
+#: g10/g10.c:480
msgid "conflicting commands\n"
msgstr "commandes en conflit\n"
-#: g10/g10.c:616
+#: g10/g10.c:618
#, c-format
msgid "NOTE: no default option file '%s'\n"
msgstr "NOTE : pas de fichier d'options par défaut '%s'\n"
-#: g10/g10.c:620
+#: g10/g10.c:622
#, c-format
msgid "option file '%s': %s\n"
msgstr "fichier d'options '%s' : %s\n"
-#: g10/g10.c:627
+#: g10/g10.c:629
#, c-format
msgid "reading options from '%s'\n"
msgstr "lire les options de '%s'\n"
-#: g10/g10.c:776
+#: g10/g10.c:782
#, c-format
msgid "%s is not a valid character set\n"
msgstr "%s n'est pas une table de caractères valide\n"
-#: g10/g10.c:810 g10/g10.c:822
+#: g10/g10.c:817 g10/g10.c:829
msgid "selected cipher algorithm is invalid\n"
msgstr "l'algorithme de chiffrement sélectionné est invalide\n"
-#: g10/g10.c:816 g10/g10.c:828
+#: g10/g10.c:823 g10/g10.c:835
msgid "selected digest algorithm is invalid\n"
msgstr "la fonction de hachage sélectionnée est invalide\n"
-#: g10/g10.c:831
+#: g10/g10.c:838
#, c-format
msgid "compress algorithm must be in range %d..%d\n"
msgstr "l'algorithme de compression doit faire partie de l'échelle %d..%d\n"
-#: g10/g10.c:833
+#: g10/g10.c:840
msgid "completes-needed must be greater than 0\n"
msgstr "« completes-needed » doit être supérieur à 0\n"
-#: g10/g10.c:835
+#: g10/g10.c:842
msgid "marginals-needed must be greater than 1\n"
msgstr "« marginals-needed » doit être supérieur à 1\n"
-#: g10/g10.c:837
+#: g10/g10.c:844
msgid "max-cert-depth must be in range 1 to 255\n"
msgstr "« max-cert-depth » doit être compris entre 1 et 255\n"
-#: g10/g10.c:840
+#: g10/g10.c:847
msgid "NOTE: simple S2K mode (0) is strongly discouraged\n"
msgstr "NOTE : le mode S2K simple (0) est fortement déconseillé\n"
-#: g10/g10.c:844
+#: g10/g10.c:851
msgid "invalid S2K mode; must be 0, 1 or 3\n"
msgstr "mode S2K invalide ; doit être 0, 1 ou 3\n"
-#: g10/g10.c:927
+#: g10/g10.c:934
#, c-format
msgid "failed to initialize the TrustDB: %s\n"
msgstr "n'a pas pu initialiser la base de confiance : %s\n"
-#: g10/g10.c:933
+#: g10/g10.c:940
msgid "--store [filename]"
msgstr "--store [nom du fichier]"
-#: g10/g10.c:941
+#: g10/g10.c:948
msgid "--symmetric [filename]"
msgstr "--symmetric [nom du fichier]"
-#: g10/g10.c:949
+#: g10/g10.c:956
msgid "--encrypt [filename]"
msgstr "--encrypt [nom du fichier]"
-#: g10/g10.c:962
+#: g10/g10.c:969
msgid "--sign [filename]"
msgstr "--sign [nom du fichier]"
-#: g10/g10.c:975
+#: g10/g10.c:982
msgid "--sign --encrypt [filename]"
msgstr "--sign --encrypt [nom du fichier]"
-#: g10/g10.c:989
+#: g10/g10.c:996
msgid "--clearsign [filename]"
msgstr "--clearsign [nom du fichier]"
-#: g10/g10.c:1001
+#: g10/g10.c:1008
msgid "--decrypt [filename]"
msgstr "--decrypt [nom du fichier]"
-#: g10/g10.c:1010
+#: g10/g10.c:1017
msgid "--edit-key username [commands]"
msgstr "--edit-key utilisateur [commandes]"
-#: g10/g10.c:1026
+#: g10/g10.c:1033
msgid "--delete-secret-key username"
msgstr "--delete-secret-key utilisateur"
-#: g10/g10.c:1029
+#: g10/g10.c:1036
msgid "--delete-key username"
msgstr "--delete-key utilisateur"
-#: g10/encode.c:216 g10/g10.c:1052 g10/sign.c:301
+#: g10/encode.c:216 g10/g10.c:1059 g10/sign.c:301
#, c-format
msgid "can't open %s: %s\n"
msgstr "ne peut ouvrir %s: %s\n"
-#: g10/g10.c:1063
+#: g10/g10.c:1070
msgid "-k[v][v][v][c] [userid] [keyring]"
msgstr "-k[v][v][v][c] [utilisateur] [porte-clés]"
-#: g10/g10.c:1120
+#: g10/g10.c:1127
#, c-format
msgid "dearmoring failed: %s\n"
msgstr "suppression d'armure non réussie : %s\n"
-#: g10/g10.c:1128
+#: g10/g10.c:1135
#, c-format
msgid "enarmoring failed: %s\n"
msgstr "construction d'armure non réussie : %s \n"
-#: g10/g10.c:1194
+#: g10/g10.c:1201
#, c-format
msgid "invalid hash algorithm '%s'\n"
msgstr "algorithme de hachage '%s' invalide\n"
-#: g10/g10.c:1273
+#: g10/g10.c:1280
msgid "[filename]"
msgstr "[nom du fichier]"
-#: g10/g10.c:1277
+#: g10/g10.c:1284
msgid "Go ahead and type your message ...\n"
msgstr "Continuez et tapez votre message...\n"
-#: g10/decrypt.c:59 g10/g10.c:1280 g10/verify.c:66
+#: g10/decrypt.c:59 g10/g10.c:1287 g10/verify.c:66
#, c-format
msgid "can't open '%s'\n"
msgstr "ne peut ouvrir '%s'\n"
#: g10/armor.c:344 g10/armor.c:391
msgid "armor header: "
msgstr "en-tête d'armure : "
#: g10/armor.c:355
msgid "invalid clearsig header\n"
msgstr "en-tête de signature claire invalide\n"
#: g10/armor.c:382
msgid "invalid armor header: "
msgstr "en-tête d'armure invalide : "
#: g10/armor.c:460
#, c-format
msgid "armor: %s\n"
msgstr "armure : %s\n"
#: g10/armor.c:533
msgid "invalid dash escaped line: "
msgstr "ligne de traits d'échappement invalide : "
#: g10/armor.c:602
msgid "invalid clear text header: "
msgstr "en-tête de texte clair invalide : "
#: g10/armor.c:845
#, c-format
msgid "invalid radix64 character %02x skipped\n"
msgstr "caractère %02x invalide en base 64 ignoré\n"
#: g10/armor.c:878
msgid "premature eof (no CRC)\n"
msgstr "fin de fichier prématurée (pas de CRC)\n"
#: g10/armor.c:897
msgid "premature eof (in CRC)\n"
msgstr "fin de fichier prématurée (dans le CRC)\n"
#: g10/armor.c:901
msgid "malformed CRC\n"
msgstr "CRC malformé\n"
#: g10/armor.c:905
#, c-format
msgid "CRC error; %06lx - %06lx\n"
msgstr "Erreur de CRC ; %06lx - %06lx\n"
#: g10/armor.c:924
msgid "premature eof (in Trailer)\n"
msgstr "fin de fichier prématurée (dans la remorque)\n"
#: g10/armor.c:928
msgid "error in trailer line\n"
msgstr "erreur dans la ligne de remorque\n"
#: g10/armor.c:1182
msgid "no valid RFC1991 or OpenPGP data found.\n"
msgstr "pas de donnée RFC1991 ou OpenPGP valide trouvée.\n"
-#: g10/pkclist.c:121
+#: g10/pkclist.c:138
#, c-format
msgid ""
"No trust value assigned to %lu:\n"
"%4u%c/%08lX %s \""
msgstr ""
"Pas de confiance définie pour %lu :\n"
"%4u%c/%08lX %s \""
-#: g10/pkclist.c:131
+#: g10/pkclist.c:148
msgid ""
"Please decide how far you trust this user to correctly\n"
"verify other users' keys (by looking at passports,\n"
"checking fingerprints from different sources...)?\n"
"\n"
" 1 = Don't know\n"
" 2 = I do NOT trust\n"
" 3 = I trust marginally\n"
" 4 = I trust fully\n"
" s = please show me more information\n"
msgstr ""
"Décidez à quel point vous avez confiance en cet utilisateur pour vérifier\n"
"correctement les clés des autres utilisateurs (en regardant des passeports,\n"
"en vérifiant les empreintes de diverses sources...)?\n"
"\n"
" 1 = je ne sais pas\n"
" 2 = je ne lui fais pas confiance\n"
" 3 = je le crois marginalement\n"
" 4 = je le crois totalement\n"
" s = montrez moi plus d'informations\n"
-#: g10/pkclist.c:140
+#: g10/pkclist.c:157
msgid " m = back to the main menu\n"
msgstr " m = retour au menu principal\n"
+#: g10/pkclist.c:159
+msgid " q = quit\n"
+msgstr ""
+
#. a string with valid answers
-#: g10/pkclist.c:145
-msgid "sSmM"
-msgstr "sSmM"
+#: g10/pkclist.c:164
+#, fuzzy
+msgid "sSmMqQ"
+msgstr "sSmMqQ"
-#: g10/pkclist.c:149
+#: g10/pkclist.c:168
msgid "Your decision? "
msgstr "Votre décision ? "
-#: g10/pkclist.c:169
+#: g10/pkclist.c:188
msgid "Certificates leading to an ultimately trusted key:\n"
msgstr "Certificats conduisant vers une clé à confiance ultime :\n"
-#: g10/pkclist.c:197
+#: g10/pkclist.c:221
msgid ""
"Could not find a valid trust path to the key. Let's see whether we\n"
"can assign some missing owner trust values.\n"
"\n"
msgstr ""
"N'a pas pu trouver un chemin de confiance valide jusqu'à la clé. Voyons si\n"
"nous ne pouvons pas assigner quelques indices de confiance manquants.\n"
-#: g10/pkclist.c:219
+#: g10/pkclist.c:251
msgid ""
"No path leading to one of our keys found.\n"
"\n"
msgstr ""
"Aucun chemin menant vers une de nos clés n'a été trouvé.\n"
"\n"
-#: g10/pkclist.c:221
+#: g10/pkclist.c:253
msgid ""
"No certificates with undefined trust found.\n"
"\n"
msgstr ""
"Aucun certificat à confiance indéfinie n'a été trouvé.\n"
"\n"
-#: g10/pkclist.c:223
+#: g10/pkclist.c:255
msgid ""
"No trust values changed.\n"
"\n"
msgstr ""
"Pas d'indice de confiance changé.\n"
"\n"
-#: g10/pkclist.c:238
+#: g10/pkclist.c:270
#, c-format
msgid "key %08lX: key has been revoked!\n"
msgstr "clé %08lX : la clé a été révoquée !\n"
-#: g10/pkclist.c:244 g10/pkclist.c:335
+#: g10/pkclist.c:276 g10/pkclist.c:369
msgid "Use this key anyway? "
msgstr "Utiliser cette clé quand-même ? "
-#: g10/pkclist.c:266
+#: g10/pkclist.c:298
#, c-format
msgid "%08lX: key has expired\n"
msgstr "%08lX : la clé a expiré\n"
-#: g10/pkclist.c:272
+#: g10/pkclist.c:304
#, c-format
msgid "%08lX: no info to calculate a trust probability\n"
msgstr "%08lX : pas d'information pour calculer une probabilité de confiance\n"
-#: g10/pkclist.c:288
+#: g10/pkclist.c:322
#, c-format
msgid "%08lX: We do NOT trust this key\n"
msgstr "%08lX : Nous ne faisons PAS confiance à cette clé\n"
-#: g10/pkclist.c:294
+#: g10/pkclist.c:328
#, c-format
msgid ""
"%08lX: It is not sure that this key really belongs to the owner\n"
"but it is accepted anyway\n"
msgstr ""
"%08lX : Il n'est pas sûr que cette clé appartient vraiment à son "
"propriétaire\n"
"mais elle est quand même acceptée\n"
-#: g10/pkclist.c:300
+#: g10/pkclist.c:334
msgid "This key probably belongs to the owner\n"
msgstr "Cette clé appartient probablement à son propriétaire\n"
-#: g10/pkclist.c:305
+#: g10/pkclist.c:339
msgid "This key belongs to us\n"
msgstr "Cette clé nous appartient\n"
-#: g10/pkclist.c:330
+#: g10/pkclist.c:364
msgid ""
"It is NOT certain that the key belongs to its owner.\n"
"If you *really* know what you are doing, you may answer\n"
"the next question with yes\n"
"\n"
msgstr ""
"Il n'est pas certain que la clé appartient à sos propriétaire.\n"
"Si vous savez *vraiment* ce que vous faites, vous pouvez répondre\n"
"oui à la prochaine question\n"
"\n"
-#: g10/pkclist.c:339
+#: g10/pkclist.c:373
msgid "WARNING: Using untrusted key!\n"
msgstr "ATTENTION : Utilisation d'une clé sans confiance !\n"
-#: g10/pkclist.c:375
+#: g10/pkclist.c:409
msgid "WARNING: This key has been revoked by its owner!\n"
msgstr "ATTENTION : Cette clé à été révoquée par son propriétaire !\n"
-#: g10/pkclist.c:376
+#: g10/pkclist.c:410
msgid " This could mean that the signature is forgery.\n"
msgstr " Cela pourrait signifier que la signature est fausse.\n"
-#: g10/pkclist.c:397
+#: g10/pkclist.c:431
msgid "Note: This key has expired!\n"
msgstr "Note : Cette clé a expiré !\n"
-#: g10/pkclist.c:404
+#: g10/pkclist.c:438
msgid "WARNING: This key is not certified with a trusted signature!\n"
msgstr ""
"ATTENTION : Cette clé n'est pas certifiée avec une signature de confiance !\n"
-#: g10/pkclist.c:406
+#: g10/pkclist.c:440
msgid ""
" There is no indication that the signature belongs to the owner.\n"
msgstr " Rien ne dit que la signature appartient à son propriétaire.\n"
-#: g10/pkclist.c:421
+#: g10/pkclist.c:456
msgid "WARNING: We do NOT trust this key!\n"
msgstr "ATTENTION : Nous ne faisons PAS confiance à cette clé !\n"
-#: g10/pkclist.c:422
+#: g10/pkclist.c:457
msgid " The signature is probably a FORGERY.\n"
msgstr " La signature est certainement FAUSSE.\n"
-#: g10/pkclist.c:429
+#: g10/pkclist.c:464
msgid ""
"WARNING: This key is not certified with sufficiently trusted signatures!\n"
msgstr ""
"ATTENTION : Les signatures de cette clé n'ont pas une confiance suffisante "
"!\n"
-#: g10/pkclist.c:432
+#: g10/pkclist.c:467
msgid " It is not certain that the signature belongs to the owner.\n"
msgstr ""
" Il n'est pas sûr que la signature appartient à son propriétaire.\n"
-#: g10/pkclist.c:477
+#: g10/pkclist.c:512
msgid ""
"You did not specify a user ID. (you may use \"-r\")\n"
"\n"
msgstr ""
"Vous n'avez pas spécifié de nom d'utilisateur. (vous pouvez utiliser "
"\"-r\")\n"
"\n"
-#: g10/pkclist.c:482
+#: g10/pkclist.c:517
msgid "Enter the user ID: "
msgstr "Entrez le nom d'utilisateur : "
-#: g10/pkclist.c:493
+#: g10/pkclist.c:528
msgid "No such user ID.\n"
msgstr "Pas de tel utilisateur.\n"
-#: g10/pkclist.c:527 g10/pkclist.c:554
+#: g10/pkclist.c:562 g10/pkclist.c:589
#, c-format
msgid "%s: skipped: %s\n"
msgstr "%s : ignoré : %s\n"
-#: g10/pkclist.c:535
+#: g10/pkclist.c:570
#, c-format
msgid "%s: error checking key: %s\n"
msgstr "%s : erreur pendant la vérification de la clé : %s\n"
-#: g10/pkclist.c:561
+#: g10/pkclist.c:596
msgid "no valid addressees\n"
msgstr "pas de destinataire valide\n"
# g10/keygen.c:123 ???
#: g10/keygen.c:124
msgid "writing self signature\n"
msgstr "écriture de l'auto-signature\n"
# g10/keygen.c:161 ???
#: g10/keygen.c:162
msgid "writing key binding signature\n"
msgstr "écriture de la signature de liaison\n"
#: g10/keygen.c:388
msgid "Please select what kind of key you want:\n"
msgstr "Sélectionnez le type de clé désiré :\n"
#: g10/keygen.c:390
#, c-format
msgid " (%d) DSA and ElGamal (default)\n"
msgstr " (%d) DSA et ElGamal (défaut)\n"
#: g10/keygen.c:391
#, c-format
msgid " (%d) DSA (sign only)\n"
msgstr " (%d) DSA (signature seule)\n"
#: g10/keygen.c:393
#, c-format
msgid " (%d) ElGamal (encrypt only)\n"
msgstr " (%d) ElGamal (chiffrement seul)\n"
#: g10/keygen.c:394
#, c-format
msgid " (%d) ElGamal (sign and encrypt)\n"
msgstr " (%d) ElGamal (signature et chiffrement)\n"
#: g10/keygen.c:396
#, c-format
msgid " (%d) ElGamal in a v3 packet\n"
msgstr " (%d) ElGamal dans un paquet v3\n"
#: g10/keygen.c:401
msgid "Your selection? "
msgstr "Votre choix ? "
#: g10/keygen.c:411
msgid "Do you really want to create a sign and encrypt key? "
msgstr "Voulez-vous vraiment créer une clé de signature et de chiffrement ? "
#: g10/keygen.c:432
msgid "Invalid selection.\n"
msgstr "Choix invalide.\n"
#: g10/keygen.c:444
#, c-format
msgid ""
"About to generate a new %s keypair.\n"
" minimum keysize is 768 bits\n"
" default keysize is 1024 bits\n"
" highest suggested keysize is 2048 bits\n"
msgstr ""
"Préparation à la génération d'une nouvelle paire de clés %s.\n"
" la taille minimale est 768 bits\n"
" la taille par défaut est 1024 bits\n"
" la taille maximale conseillée est 2048 bits\n"
#: g10/keygen.c:451
msgid "What keysize do you want? (1024) "
msgstr "Quelle taille de clé désirez-vous ? (1024) "
#: g10/keygen.c:456
msgid "DSA only allows keysizes from 512 to 1024\n"
msgstr "DSA permet seulement des tailles comprises entre 512 et 1024\n"
#: g10/keygen.c:458
msgid "keysize too small; 768 is smallest value allowed.\n"
msgstr "taille trop petite ; 768 est la plus petite valeur permise.\n"
#: g10/keygen.c:461
msgid ""
"Keysizes larger than 2048 are not suggested because\n"
"computations take REALLY long!\n"
msgstr ""
"Les tailles supérieures à 2048 ne sont pas conseillées car\n"
"les calculs sont VRAIMENT longs!\n"
#: g10/keygen.c:464
msgid "Are you sure that you want this keysize? "
msgstr "Etes-vous sûr de vouloir cette taille ? "
#: g10/keygen.c:465
msgid ""
"Okay, but keep in mind that your monitor and keyboard radiation is also very "
"vulnerable to attacks!\n"
msgstr ""
"D'accord, mais n'oubliez pas que votre écran et les radiations du clavier "
"sont aussi très vulnérables aux attaques!\n"
#: g10/keygen.c:473
msgid "Do you really need such a large keysize? "
msgstr "Avez-vous réellement besoin d'une taille aussi grande ? "
#: g10/keygen.c:479
#, c-format
msgid "Requested keysize is %u bits\n"
msgstr "La taille demandée est %u bits\n"
#: g10/keygen.c:482 g10/keygen.c:486
#, c-format
msgid "rounded up to %u bits\n"
msgstr "arrondie à %u bits\n"
#: g10/keygen.c:499
msgid ""
"Please specify how long the key should be valid.\n"
" 0 = key does not expire\n"
" <n> = key expires in n days\n"
" <n>w = key expires in n weeks\n"
" <n>m = key expires in n months\n"
" <n>y = key expires in n years\n"
msgstr ""
"Spécifiez combien de temps cette clé devrait être valide.\n"
" 0 = la clé n'expire pas\n"
" <n> = la clé expire dans n jours\n"
" <n>w = la clé expire dans n semaines\n"
" <n>m = la clé expire dans n mois\n"
" <n>y = la clé expire dans n ans\n"
#: g10/keygen.c:514
msgid "Key is valid for? (0) "
msgstr "La clé est valide pour ? (0) "
#: g10/keygen.c:525
msgid "invalid value\n"
msgstr "valeur invalide\n"
#: g10/keygen.c:530
msgid "Key does not expire at all\n"
msgstr "La clé n'expire pas du tout\n"
#. print the date when the key expires
#: g10/keygen.c:536
#, c-format
msgid "Key expires at %s\n"
msgstr "La clé expire le %s\n"
#: g10/keygen.c:542
msgid "Is this correct (y/n)? "
msgstr "Est-ce correct (o/n) ? "
#: g10/keygen.c:584
msgid ""
"\n"
"You need a User-ID to identify your key; the software constructs the user "
"id\n"
"from Real Name, Comment and Email Address in this form:\n"
" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n"
"\n"
msgstr ""
"\n"
"Vous avez besoin d'un nom d'utilisateur pour identifier votre clé ; le\n"
"programme le construit à partir du nom réel, d'un commentaire et d'une\n"
"adresse e-mail de cette manière:\n"
" « Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de> »\n"
"\n"
#: g10/keygen.c:595
msgid "Real name: "
msgstr "Nom réel : "
#: g10/keygen.c:599
msgid "Invalid character in name\n"
msgstr "Caractère invalide dans le nom\n"
#: g10/keygen.c:601
msgid "Name may not start with a digit\n"
msgstr "Le nom ne doit pas commencer avec un chiffre\n"
# ??? c'est de la discrimination...
#: g10/keygen.c:603
msgid "Name must be at least 5 characters long\n"
msgstr "Le nom doit faire au moins 5 caractères de long\n"
#: g10/keygen.c:611
msgid "Email address: "
msgstr "Adresse e-mail : "
#: g10/keygen.c:623
msgid "Not a valid email address\n"
msgstr "Ce n'est pas une adresse e-mail valide\n"
#: g10/keygen.c:631
msgid "Comment: "
msgstr "Commentaire : "
#: g10/keygen.c:637
msgid "Invalid character in comment\n"
msgstr "Caractère invalide dans le commentaire\n"
#: g10/keygen.c:657
#, c-format
msgid ""
"You selected this USER-ID:\n"
" \"%s\"\n"
"\n"
msgstr ""
"Vous avez sélectionné ce nom d'utilisateur :\n"
" \"%s\"\n"
"\n"
#: g10/keygen.c:660
msgid "NnCcEeOoQq"
msgstr "NnCcEeOoQq"
#: g10/keygen.c:670
msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? "
msgstr "Changer le (N)om, le (C)ommentaire, l'(E)-mail ou (O)K/(Q)uitter? "
#: g10/keygen.c:722
msgid ""
"You need a Passphrase to protect your secret key.\n"
"\n"
msgstr ""
"Vous avez besoin d'un mot de passe pour protéger votre clé secrète.\n"
"\n"
#: g10/keyedit.c:389 g10/keygen.c:730
msgid "passphrase not correctly repeated; try again.\n"
msgstr "le mot de passe n'a pas été identiquement répété ; recommencez.\n"
#: g10/keygen.c:736
msgid ""
"You don't want a passphrase - this is probably a *bad* idea!\n"
"I will do it anyway. You can change your passphrase at any time,\n"
"using this program with the option \"--edit-key\".\n"
"\n"
msgstr ""
"Vous ne voulez pas de mot de passe - c'est sûrement une *mauvaise* idée !\n"
"Je l'accepte quand-même. Vous pouvez changer votre mot de passe quand vous\n"
"le désirez, en utilisant ce programme avec l'option « --edit-key ».\n"
"\n"
#: g10/keygen.c:757
msgid ""
"We need to generate a lot of random bytes. It is a good idea to perform\n"
"some other action (work in another window, move the mouse, utilize the\n"
"network and the disks) during the prime generation; this gives the random\n"
"number generator a better chance to gain enough entropy.\n"
msgstr ""
"Beaucoup d'octets aléatoires doivent être générés. Vous devriez\n"
"faire quelque-chose d'autre (travailler dans une autre fenêtre, bouger la\n"
"souris, utiliser le réseau et les disques) pendant la génération de nombres\n"
"premiers ; cela permet au générateur de nombres aléatoires d'obtenir une\n"
"entropie suffisante plus facilement.\n"
#: g10/keygen.c:827
msgid "Key generation can only be used in interactive mode\n"
msgstr "La génération de clé ne peut être faite qu'en mode interactif\n"
#: g10/keygen.c:835
msgid "DSA keypair will have 1024 bits.\n"
msgstr "La paire de clés DSA fera 1024 bits.\n"
#: g10/keygen.c:841
msgid "Key generation cancelled.\n"
msgstr "La génération a été annulée.\n"
#: g10/keygen.c:851
#, c-format
msgid "writing public certificate to '%s'\n"
msgstr "écriture d'un certificat public à '%s'\n"
#: g10/keygen.c:852
#, c-format
msgid "writing secret certificate to '%s'\n"
msgstr "écriture d'un certificat secret à '%s'\n"
#: g10/keygen.c:929
msgid "public and secret key created and signed.\n"
msgstr "les clés publique et secrète ont été créées et signées.\n"
#: g10/keygen.c:931
msgid ""
"Note that this key cannot be used for encryption. You may want to use\n"
"the command \"--add-key\" to generate a secondary key for this purpose.\n"
msgstr ""
"Notez que cette clé ne peut être utilisée pour chiffrer. Vous pouvez\n"
"utiliser la commande « --add-key » pour générer une clé secondaire à\n"
"cette fin.\n"
#: g10/keygen.c:945 g10/keygen.c:1030
#, c-format
msgid "Key generation failed: %s\n"
msgstr "La génération de clé a échoué : %s\n"
#: g10/keygen.c:1008
msgid "Really create? "
msgstr "Créer vraiment ? "
#: g10/encode.c:88 g10/openfile.c:81 g10/openfile.c:158 g10/tdbio.c:445
#: g10/tdbio.c:504
#, c-format
msgid "%s: can't open: %s\n"
msgstr "%s : ne peut ouvrir : %s\n"
#: g10/encode.c:107
#, c-format
msgid "error creating passphrase: %s\n"
msgstr "erreur pendant la création du mot de passe : %s\n"
#: g10/encode.c:155 g10/encode.c:269
#, c-format
msgid "%s: WARNING: empty file\n"
msgstr "%s : ATTENTION : fichier vide\n"
#: g10/encode.c:222
#, c-format
msgid "reading from '%s'\n"
msgstr "lecture de '%s'\n"
#: g10/encode.c:397
#, c-format
msgid "%s/%s encrypted for: %s\n"
msgstr "%s/%s chiffré pour : %s\n"
#: g10/export.c:114
#, c-format
msgid "%s: user not found: %s\n"
msgstr "%s : utilisateur non trouvé : %s\n"
#: g10/export.c:123
#, c-format
msgid "certificate read problem: %s\n"
msgstr "problème lors de lecture du certificat : %s\n"
#: g10/export.c:132
#, c-format
msgid "key %08lX: not a rfc2440 key - skipped\n"
msgstr "clé %08lX : ce n'est pas une clé rfc2440 - ignorée\n"
#: g10/export.c:174
msgid "WARNING: nothing exported\n"
msgstr "ATTENTION : rien n'a été exporté\n"
#: g10/getkey.c:164
msgid "too many entries in pk cache - disabled\n"
msgstr "trop d'entrées dans le cache pk - désactivé\n"
#: g10/getkey.c:263
msgid "too many entries in unk cache - disabled\n"
msgstr "trop d'entrées dans le cache unk - désactivé\n"
#: g10/getkey.c:989
#, c-format
msgid "using secondary key %08lX instead of primary key %08lX\n"
msgstr ""
"utilisation de la clé secondaire %08lX à la place de la clé\n"
"principale %08lX\n"
-#: g10/import.c:129 g10/trustdb.c:1166
+#: g10/import.c:129 g10/trustdb.c:1180
#, c-format
msgid "can't open file: %s\n"
msgstr "ne peut ouvrir le fichier : %s\n"
#: g10/import.c:145
#, c-format
msgid "skipping block of type %d\n"
msgstr "ne prend pas en compte le bloc de type %d\n"
-#: g10/import.c:152 g10/trustdb.c:1425 g10/trustdb.c:1494
+#: g10/import.c:152 g10/trustdb.c:1474 g10/trustdb.c:1543
#, c-format
msgid "%lu keys so far processed\n"
msgstr "%lu clés traitées jusqu'ici\n"
-#: g10/import.c:157 g10/trustdb.c:1242
+#: g10/import.c:157 g10/trustdb.c:1256
#, c-format
msgid "read error: %s\n"
msgstr "erreur de lecture : %s\n"
#: g10/import.c:159
#, c-format
msgid "Total number processed: %lu\n"
msgstr " Quantité totale traitée : %lu\n"
#: g10/import.c:161
#, c-format
msgid " w/o user IDs: %lu\n"
msgstr " sans nom d'utilisateur : %lu\n"
#: g10/import.c:163
#, c-format
msgid " imported: %lu"
msgstr " importée : %lu"
#: g10/import.c:169
#, c-format
msgid " unchanged: %lu\n"
msgstr " inchangée : %lu\n"
#: g10/import.c:171
#, c-format
msgid " new user IDs: %lu\n"
msgstr " nouveaux noms d'utilisateurs : %lu\n"
#: g10/import.c:173
#, c-format
msgid " new subkeys: %lu\n"
msgstr " nouvelles sous-clés : %lu\n"
#: g10/import.c:175
#, c-format
msgid " new signatures: %lu\n"
msgstr " nouvelles signatures : %lu\n"
#: g10/import.c:177
#, c-format
msgid " new key revocations: %lu\n"
msgstr " nouvelles révocations de clés : %lu\n"
#: g10/import.c:179
#, c-format
msgid " secret keys read: %lu\n"
msgstr " clés secrètes lues : %lu\n"
#: g10/import.c:181
#, c-format
msgid " secret keys imported: %lu\n"
msgstr " clés secrètes importées : %lu\n"
#: g10/import.c:183
#, c-format
msgid " secret keys unchanged: %lu\n"
msgstr " clés secrètes inchangées : %lu\n"
#: g10/import.c:325 g10/import.c:517
#, c-format
msgid "key %08lX: no user id\n"
msgstr "clé %08lX : pas de nom d'utilisateur\n"
#: g10/import.c:336
#, c-format
msgid "key %08lX: no valid user ids\n"
msgstr "clé %08lX : pas de nom d'utilisateur valide\n"
#: g10/import.c:338
msgid "this may be caused by a missing self-signature\n"
msgstr "cela peut provenir d'une auto-signature manquante\n"
#: g10/import.c:349 g10/import.c:585
#, c-format
msgid "key %08lX: public key not found: %s\n"
msgstr "clé %08lX : clé publique pas trouvée: %s\n"
#: g10/import.c:355
msgid "no default public keyring\n"
msgstr "pas de porte-clés public par défaut\n"
-#: g10/import.c:359 g10/openfile.c:105 g10/sign.c:205 g10/sign.c:569
+#: g10/import.c:359 g10/openfile.c:105 g10/sign.c:205 g10/sign.c:592
#, c-format
msgid "writing to '%s'\n"
msgstr "écriture de '%s'\n"
#: g10/import.c:363 g10/import.c:423 g10/import.c:639
#, c-format
msgid "can't lock public keyring: %s\n"
msgstr "ne peut verrouiller le porte-clés public : %s\n"
#: g10/import.c:366
#, c-format
msgid "can't write to keyring: %s\n"
msgstr "ne peut écrire le porte-clés : %s\n"
#: g10/import.c:370
#, c-format
msgid "key %08lX: public key imported\n"
msgstr "clé %08lX : clé publique importée\n"
#: g10/import.c:383
#, c-format
msgid "key %08lX: doesn't match our copy\n"
msgstr "clé %08lX : ne ressemble pas à notre copie\n"
#: g10/import.c:396 g10/import.c:594
#, c-format
msgid "key %08lX: can't locate original keyblock: %s\n"
msgstr "clé %08lX : ne peut trouver le bloc de clés original : %s\n"
#: g10/import.c:403 g10/import.c:601
#, c-format
msgid "key %08lX: can't read original keyblock: %s\n"
msgstr "clé %08lX : ne peut lire le bloc de clés original : %s\n"
#: g10/import.c:420 g10/import.c:532 g10/import.c:636
msgid "writing keyblock\n"
msgstr "écriture du bloc de clés\n"
#: g10/import.c:426 g10/import.c:642
#, c-format
msgid "can't write keyblock: %s\n"
msgstr "ne peut écrire le bloc de clés : %s\n"
#: g10/import.c:431
#, c-format
msgid "key %08lX: 1 new user-id\n"
msgstr "clé %08lX : un nouvel utilisateur\n"
#: g10/import.c:434
#, c-format
msgid "key %08lX: %d new user-ids\n"
msgstr "clé %08lX : %d nouveaux utilisateurs\n"
#: g10/import.c:437
#, c-format
msgid "key %08lX: 1 new signature\n"
msgstr "clé %08lX : une nouvelle signature\n"
#: g10/import.c:440
#, c-format
msgid "key %08lX: %d new signatures\n"
msgstr "clé %08lX : %d nouvelles signatures\n"
#: g10/import.c:443
#, c-format
msgid "key %08lX: 1 new subkey\n"
msgstr "clé %08lX : une nouvelle sous-clé\n"
#: g10/import.c:446
#, c-format
msgid "key %08lX: %d new subkeys\n"
msgstr "clé %08lX : %d nouvelles sous-clés\n"
#: g10/import.c:456
#, c-format
msgid "key %08lX: not changed\n"
msgstr "clé %08lX : n'a pas changé\n"
#: g10/import.c:535
#, c-format
msgid "can't lock secret keyring: %s\n"
msgstr "ne peut verrouiller le porte-clés secret : %s\n"
#: g10/import.c:538
#, c-format
msgid "can't write keyring: %s\n"
msgstr "ne peut écrire le porte-clés : %s\n"
#. we are ready
#: g10/import.c:541
#, c-format
msgid "key %08lX: secret key imported\n"
msgstr "clé %08lX : clé secrète importée\n"
#. we can't merge secret keys
#: g10/import.c:545
#, c-format
msgid "key %08lX: already in secret keyring\n"
msgstr "clé %08lX : déjà dans le porte-clés secret\n"
#: g10/import.c:550
#, c-format
msgid "key %08lX: secret key not found: %s\n"
msgstr "clé %08lX : clé secrète pas trouvée: %s\n"
#: g10/import.c:579
#, c-format
msgid "key %08lX: no public key - can't apply revocation certificate\n"
msgstr ""
"clé %08lX : pas de clé publique - ne peut appliquer le certificat de\n"
"révocation\n"
#: g10/import.c:612
#, c-format
msgid "key %08lX: invalid revocation certificate: %s - rejected\n"
msgstr "clé %08lX : certificat de révocation invalide : %s - rejeté\n"
#: g10/import.c:646
#, c-format
msgid "key %08lX: revocation certificate imported\n"
msgstr "clé %08lX : certificat de révocation importé\n"
#: g10/import.c:677
#, c-format
msgid "key %08lX: no user-id for signature\n"
msgstr "clé %08lX : pas d'utilisateur pour la signature\n"
#: g10/import.c:684
#, c-format
msgid "key %08lX: unsupported public key algorithm\n"
msgstr "clé %08lX : algorithme de clé publique non supporté\n"
#: g10/import.c:685
#, c-format
msgid "key %08lX: invalid self-signature\n"
msgstr "clé %08lX : auto-signature invalide\n"
#: g10/import.c:714
#, c-format
msgid "key %08lX: skipped userid '"
msgstr "clé %08lX : utilisateur non pris en compte '"
#: g10/import.c:737
#, c-format
msgid "key %08lX: revocation certificate at wrong place - skipped\n"
msgstr "clé %08lX : certificat de révocation au mauvais endroit - ignorée\n"
#: g10/import.c:745
#, c-format
msgid "key %08lX: invalid revocation certificate: %s - skipped\n"
msgstr "clé %08lX : certificat de révocation invalide : %s - ignorée\n"
#: g10/import.c:804
#, c-format
msgid "key %08lX: revocation certificate added\n"
msgstr "clé %08lX : certificat de révocation ajouté\n"
#: g10/import.c:918 g10/import.c:973
#, c-format
msgid "key %08lX: our copy has no self-signature\n"
msgstr "clé %08lX : notre copie n'a pas d'auto-signature\n"
#: g10/keyedit.c:81
#, c-format
msgid "%s: user not found\n"
msgstr "%s : utilisateur non trouvé\n"
#: g10/keyedit.c:164
msgid "[self-signature]"
msgstr "[auto-signature]"
#: g10/keyedit.c:182
msgid "1 bad signature\n"
msgstr "une mauvaise signature\n"
#: g10/keyedit.c:184
#, c-format
msgid "%d bad signatures\n"
msgstr "%d mauvaises signatures\n"
#: g10/keyedit.c:186
msgid "1 signature not checked due to a missing key\n"
msgstr "une signature non vérifiée à cause d'une clé manquante\n"
#: g10/keyedit.c:188
#, c-format
msgid "%d signatures not checked due to missing keys\n"
msgstr "%d signatures non vérifiées à cause de clés manquantes\n"
#: g10/keyedit.c:190
msgid "1 signature not checked due to an error\n"
msgstr "une signature non vérifiée à cause d'une erreur\n"
#: g10/keyedit.c:192
#, c-format
msgid "%d signatures not checked due to errors\n"
msgstr "%d signatures non vérifiées à cause d'erreurs\n"
#: g10/keyedit.c:194
msgid "1 user id without valid self-signature detected\n"
msgstr "un nom d'utilisateur sans auto-signature valide détecté\n"
#: g10/keyedit.c:196
#, c-format
msgid "%d user ids without valid self-signatures detected\n"
msgstr "%d nom d'utilisateurs sans auto-signature valide détecté\n"
#: g10/keyedit.c:258
#, c-format
msgid "Already signed by key %08lX\n"
msgstr "Déjà signé par la clé %08lX\n"
#: g10/keyedit.c:266
#, c-format
msgid "Nothing to sign with key %08lX\n"
msgstr "Rien à signer avec la clé %08lX\n"
#: g10/keyedit.c:275
msgid ""
"Are you really sure that you want to sign this key\n"
"with your key: \""
msgstr ""
"Etes-vous vraiment sûr(e) que vous voulez signer cette clé\n"
"avec la vôtre : \""
#: g10/keyedit.c:282
msgid "Really sign? "
msgstr "Signer réellement ? "
#: g10/keyedit.c:303 g10/sign.c:65
#, c-format
msgid "signing failed: %s\n"
msgstr "la signature a échoué : %s\n"
#: g10/keyedit.c:356
msgid "This key is not protected.\n"
msgstr "Cette clé n'est pas protégée.\n"
#: g10/keyedit.c:359
msgid "Key is protected.\n"
msgstr "La clé est protégée.\n"
#: g10/keyedit.c:376
#, c-format
msgid "Can't edit this key: %s\n"
msgstr "Ne peut éditer cette clé : %s\n"
#: g10/keyedit.c:381
msgid ""
"Enter the new passphrase for this secret key.\n"
"\n"
msgstr "Entrez le nouveau mot de passe pour cette clé secrète.\n"
#: g10/keyedit.c:393
msgid ""
"You don't want a passphrase - this is probably a *bad* idea!\n"
"\n"
msgstr ""
"Vous ne voulez pas de mot de passe - cela est certainement une\n"
"*mauvaise* idée\n"
"\n"
#: g10/keyedit.c:396
msgid "Do you really want to do this? "
msgstr "Voulez-vous vraiment faire cela? "
#: g10/keyedit.c:455
msgid "moving a key signature to the correct place\n"
msgstr "replacer la signature d'une clé à l'endroit correct\n"
#: g10/keyedit.c:490
msgid "quit"
msgstr "quitter"
#: g10/keyedit.c:490
msgid "quit this menu"
msgstr "quitter ce menu"
#: g10/keyedit.c:491
msgid "q"
msgstr "q"
#: g10/keyedit.c:492
msgid "save"
msgstr "enregistrer"
#: g10/keyedit.c:492
msgid "save and quit"
msgstr "enregistrer et quitter"
# FIXMOI : si je mets aide ça va demander de taper "aide"...
#: g10/keyedit.c:493
msgid "help"
msgstr "help"
#: g10/keyedit.c:493
msgid "show this help"
msgstr "afficher cette aide"
# g10/keyedit.c:556 ???
#: g10/keyedit.c:495
msgid "fpr"
msgstr "fpr"
#: g10/keyedit.c:495
msgid "show fingerprint"
msgstr "afficher l'empreinte"
#: g10/keyedit.c:496
msgid "list"
msgstr "lister"
#: g10/keyedit.c:496
msgid "list key and user ids"
msgstr "lister la clé et les noms d'utilisateurs"
#: g10/keyedit.c:497
msgid "l"
msgstr "l"
#: g10/keyedit.c:498
msgid "uid"
msgstr "uid"
#: g10/keyedit.c:498
msgid "select user id N"
msgstr "sélectionner le nom d'utilisateur N"
#: g10/keyedit.c:499
msgid "key"
msgstr "clé"
#: g10/keyedit.c:499
msgid "select secondary key N"
msgstr "sélectionner la clé secondaire N"
#: g10/keyedit.c:500
msgid "check"
msgstr "vérifier"
#: g10/keyedit.c:500
msgid "list signatures"
msgstr "lister les signatures"
#: g10/keyedit.c:501
msgid "c"
msgstr "c"
#: g10/keyedit.c:502
msgid "sign"
msgstr "signer"
#: g10/keyedit.c:502
msgid "sign the key"
msgstr "signer la clé"
#: g10/keyedit.c:503
msgid "s"
msgstr "s"
#: g10/keyedit.c:504
msgid "debug"
msgstr "déboguer"
#: g10/keyedit.c:505
msgid "adduid"
msgstr "aj.ut"
#: g10/keyedit.c:505
msgid "add a user id"
msgstr "ajouter un utilisateur"
#: g10/keyedit.c:506
msgid "deluid"
msgstr "suppr.ut"
#: g10/keyedit.c:506
msgid "delete user id"
msgstr "enlever un utilisateur"
#: g10/keyedit.c:507
msgid "addkey"
msgstr "aj.clé"
#: g10/keyedit.c:507
msgid "add a secondary key"
msgstr "ajouter une clé secondaire"
#: g10/keyedit.c:508
msgid "delkey"
msgstr "suppr.clé"
#: g10/keyedit.c:508
msgid "delete a secondary key"
msgstr "enlever une clé secondaire"
#: g10/keyedit.c:509
msgid "expire"
msgstr "expire"
#: g10/keyedit.c:509
msgid "change the expire date"
msgstr "changer la date d'expiration"
#: g10/keyedit.c:510
msgid "toggle"
msgstr "changer"
#: g10/keyedit.c:510
msgid "toggle between secret and public key listing"
msgstr "passer de la liste des clés secrètes aux clés privées et inversement"
#: g10/keyedit.c:512
msgid "t"
msgstr "t"
#: g10/keyedit.c:513
msgid "pref"
msgstr "préf"
#: g10/keyedit.c:513
msgid "list preferences"
msgstr "lister les préférences"
#: g10/keyedit.c:514
msgid "passwd"
msgstr "mot.pas"
#: g10/keyedit.c:514
msgid "change the passphrase"
msgstr "changer le mot de passe"
#: g10/keyedit.c:515
msgid "trust"
msgstr "confi."
#: g10/keyedit.c:515
msgid "change the ownertrust"
msgstr "changer la confiance"
#: g10/keyedit.c:534
msgid "can't do that in batchmode\n"
msgstr "ne peut faire cela en mode automatique\n"
#. check that they match
#. FIXME: check that they both match
#: g10/keyedit.c:561
msgid "Secret key is available.\n"
msgstr "La clé secrète est disponible.\n"
#: g10/keyedit.c:590
msgid "Command> "
msgstr "Commande> "
#: g10/keyedit.c:617
msgid "Need the secret key to do this.\n"
msgstr "Il faut la clé secrète pour faire cela.\n"
#: g10/keyedit.c:639
msgid "Save changes? "
msgstr "Enregistrer les changements? "
#: g10/keyedit.c:642
msgid "Quit without saving? "
msgstr "Quitter sans enregistrer? "
#: g10/keyedit.c:652
#, c-format
msgid "update failed: %s\n"
msgstr "la mise à jour a échoué : %s\n"
#: g10/keyedit.c:659
#, c-format
msgid "update secret failed: %s\n"
msgstr "la mise à jour de la clé secrète a échoué : %s\n"
#: g10/keyedit.c:666
msgid "Key not changed so no update needed.\n"
msgstr "La clé n'a pas changé donc la mise à jour est inutile.\n"
#: g10/keyedit.c:669 g10/keyedit.c:727
#, c-format
msgid "update of trust db failed: %s\n"
msgstr "la mise à jour de la base de confiance a échoué : %s\n"
#: g10/keyedit.c:701
msgid "Really sign all user ids? "
msgstr "Signer vraiment tous les utilisateurs ? "
#: g10/keyedit.c:702
msgid "Hint: Select the user ids to sign\n"
msgstr "Aide : Sélectionner les utilisateurs à signer\n"
#: g10/keyedit.c:738
msgid "You must select at least one user id.\n"
msgstr "Vous devez sélectionner au moins un utilisateur.\n"
#: g10/keyedit.c:740
msgid "You can't delete the last user id!\n"
msgstr "Vous ne pouvez pas supprimer le dernier utilisateur !\n"
#: g10/keyedit.c:743
msgid "Really remove all selected user ids? "
msgstr "Enlever réellement tous les utilisateurs sélectionnés ? "
#: g10/keyedit.c:744
msgid "Really remove this user id? "
msgstr "Enlever réellement cet utilisateur ? "
#: g10/keyedit.c:767
msgid "You must select at least one key.\n"
msgstr "Vous devez sélectionner au moins une clé.\n"
#: g10/keyedit.c:771
msgid "Do you really want to delete the selected keys? "
msgstr "Voulez-vous vraiment supprimer les clés sélectionnées ? "
#: g10/keyedit.c:772
msgid "Do you really want to delete this key? "
msgstr "Voulez-vous vraiment supprimer cette clé ? "
#: g10/keyedit.c:819
msgid "Invalid command (try \"help\")\n"
msgstr "Commande invalide (essayez « help »)\n"
#: g10/keyedit.c:1197
msgid "Please remove selections from the secret keys.\n"
msgstr "Enlevez les sélections des clés secrètes.\n"
#: g10/keyedit.c:1203
msgid "Please select at most one secondary key.\n"
msgstr "Vous devez sélectionner au plus une clé secondaire.\n"
#: g10/keyedit.c:1207
msgid "Changing exiration time for a secondary key.\n"
msgstr "Changer la date d'expiration d'une clé secondaire.\n"
#: g10/keyedit.c:1209
msgid "Changing exiration time for the primary key.\n"
msgstr "Changer la date d'expiration de la clé principale.\n"
#: g10/keyedit.c:1250
msgid "You can't change the expiration date of a v3 key\n"
msgstr "Vous ne pouvez pas changer la date d'expiration d'une clé v3\n"
#: g10/keyedit.c:1266
msgid "No corresponding signature in secret ring\n"
msgstr "Pas de signature correspondante dans le porte-clés secret\n"
#: g10/keyedit.c:1326
#, c-format
msgid "No user id with index %d\n"
msgstr "Pas d'utilisateur avec l'index %d\n"
#: g10/keyedit.c:1371
#, c-format
msgid "No secondary key with index %d\n"
msgstr "Pas de clé secondaire avec l'index %d\n"
#: g10/mainproc.c:198
msgid "public key encrypted data: Good DEK\n"
msgstr "données chiffrées avec la clé publique : bonne clé de chiffrement\n"
#: g10/mainproc.c:201
#, c-format
msgid "public key decryption failed: %s\n"
msgstr "le déchiffrement de la clé publique a échoué : %s\n"
#: g10/mainproc.c:228
msgid "decryption okay\n"
msgstr "le déchiffrement a réussi\n"
#: g10/mainproc.c:231
#, c-format
msgid "decryption failed: %s\n"
msgstr "le déchiffrement a échoué : %s\n"
#: g10/mainproc.c:248
msgid "NOTE: sender requested \"for-your-eyes-only\"\n"
msgstr "NOTE : l'expéditeur a demandé « pour vos yeux seulement »\n"
#: g10/mainproc.c:250
#, c-format
msgid "original file name='%.*s'\n"
msgstr "nom de fichier original : '%.*s'\n"
#: g10/mainproc.c:833
msgid "signature verification suppressed\n"
msgstr "vérification de signature supprimée\n"
#: g10/mainproc.c:839
#, c-format
msgid "Signature made %.*s using %s key ID %08lX\n"
msgstr "Signature faite %.*s avec une clé %s ID %08lX\n"
#: g10/mainproc.c:847
msgid "BAD signature from \""
msgstr "MAUVAISE signature de \""
#: g10/mainproc.c:848
msgid "Good signature from \""
msgstr "Bonne signature de \""
#: g10/mainproc.c:861
#, c-format
msgid "Can't check signature: %s\n"
msgstr "Ne peut vérifier la signature : %s\n"
#: g10/mainproc.c:934
msgid "old style (PGP 2.x) signature\n"
msgstr "signature d'un ancien style (PGP 2.x)\n"
#: g10/mainproc.c:939
msgid "invalid root packet detected in proc_tree()\n"
msgstr "paquet racine invalide détecté dans proc_tree()\n"
#: g10/misc.c:88
#, c-format
msgid "can't disable core dumps: %s\n"
msgstr "ne peut empêcher la génération de fichiers core : %s\n"
#: g10/misc.c:90
msgid "WARNING: Program may create a core file!\n"
msgstr "ATTENTION : Le programme peut créer un fichier core !\n"
#: g10/misc.c:198
msgid "Experimental algorithms should not be used!\n"
msgstr "Les algorithmes expérimentaux ne devraient pas être utilisés !\n"
#: g10/misc.c:212
msgid ""
"RSA keys are deprecated; please consider creating a new key and use this key "
"in the future\n"
msgstr ""
"Les clés RSA sont déconseillées : considérez créer une nouvelle clé\n"
"et l'utiliser dans l'avenir\n"
#: g10/misc.c:233
msgid "This cipher algorithm is depreciated; please use a more standard one!\n"
msgstr ""
"Cet algorithme de chiffrement est déconseillé ; utilisez-en un\n"
"plus standard!\n"
#: g10/parse-packet.c:109
#, c-format
msgid "can't handle public key algorithm %d\n"
msgstr "ne peut gérer l'algorithme à clé publique %d\n"
#: g10/parse-packet.c:801
#, c-format
msgid "subpacket of type %d has critical bit set\n"
msgstr "un sous-paquet de type %d possède un bit critique\n"
#: g10/passphrase.c:141
msgid ""
"\n"
"You need a passphrase to unlock the secret key for\n"
"user: \""
msgstr ""
"\n"
"Vous avez besoin d'un mot de passe pour déverrouiller la clé secrète pour\n"
"l'utilisateur: \""
#: g10/passphrase.c:150
#, c-format
msgid "(%u-bit %s key, ID %08lX, created %s)\n"
msgstr "(clé de %u bits %s, ID %08lX, créée le %s)\n"
#: g10/passphrase.c:174
msgid "Enter passphrase: "
msgstr "Entrez le mot de passe : "
#: g10/passphrase.c:178
msgid "Repeat passphrase: "
msgstr "Répétez le mot de passe : "
-#: g10/plaintext.c:102
+#: g10/plaintext.c:103
msgid "data not saved; use option \"--output\" to save it\n"
msgstr ""
"données non enregistrées ; utilisez l'option \"--output\" pour\n"
"les enregistrer\n"
-#: g10/plaintext.c:215
+#: g10/plaintext.c:216
msgid "Please enter name of data file: "
msgstr "Entrez le nom d'un fichier de données : "
-#: g10/plaintext.c:236
+#: g10/plaintext.c:237
msgid "reading stdin ...\n"
msgstr "lecture de l'entrée standard...\n"
-#: g10/plaintext.c:299
+#: g10/plaintext.c:300
#, c-format
msgid "can't open signed data '%s'\n"
msgstr "ne peut ouvir les données signées '%s'\n"
#: g10/pubkey-enc.c:78
#, c-format
msgid "anonymous receiver; trying secret key %08lX ...\n"
msgstr "destinataire anonyme ; essai de la clé secrète %08lX ...\n"
#: g10/pubkey-enc.c:84
msgid "okay, we are the anonymous receiver.\n"
msgstr "d'accord, nous sommes le destinataire anonyme.\n"
#: g10/pubkey-enc.c:136
msgid "old encoding of the DEK is not supported\n"
msgstr "l'ancien codage de la clé de chiffrement (DEK) n'est pas supporté\n"
#: g10/pubkey-enc.c:183
#, c-format
msgid "NOTE: cipher algorithm %d not found in preferences\n"
msgstr ""
"NOTE : l'algorithme de chiffrement %d n'a pas été trouvé dans les "
"préférences\n"
#: g10/seckey-cert.c:56
#, c-format
msgid "protection algorithm %d is not supported\n"
msgstr "l'algorithme de protection %d n'est pas supporté\n"
#: g10/seckey-cert.c:169
msgid "Invalid passphrase; please try again ...\n"
msgstr "Mot de passe invalide ; réessayez...\n"
#: g10/seckey-cert.c:216
msgid "WARNING: Weak key detected - please change passphrase again.\n"
msgstr "ATTENTION : Mauvaise clé détectée - changez encore le mot de passe.\n"
#: g10/sig-check.c:155
msgid ""
"this is a PGP generated ElGamal key which is NOT secure for signatures!\n"
msgstr ""
"Ceci est une clé ElGamal générée par PGP qui n'est PAS sûre pour les\n"
"signatures!\n"
#: g10/sig-check.c:165
msgid "public key created in future (time warp or clock problem)\n"
msgstr ""
"clé publique créée dans le futur (voyage dans le temps ou problème\n"
"d'horloge)\n"
#: g10/sig-check.c:170
#, c-format
msgid "NOTE: signature key expired %s\n"
msgstr "NOTE : la clé de signature a expiré le %s\n"
#: g10/sig-check.c:226
msgid "assuming bad signature due to an unknown critical bit\n"
msgstr ""
"la signature est supposée être fausse car un bit critique est\n"
"inconnu\n"
#: g10/sign.c:69
#, c-format
msgid "%s signature from: %s\n"
msgstr "Signature %s de : %s\n"
-#: g10/sign.c:200 g10/sign.c:564
+#: g10/sign.c:200 g10/sign.c:587
#, c-format
msgid "can't create %s: %s\n"
msgstr "ne peut créer %s : %s\n"
#: g10/sign.c:296
msgid "signing:"
msgstr "signature :"
#: g10/sign.c:336
#, c-format
msgid "WARNING: '%s' is an empty file\n"
msgstr "ATTENTION : '%s' est un fichier vide\n"
#: g10/tdbio.c:116 g10/tdbio.c:1413
#, c-format
msgid "trustdb rec %lu: lseek failed: %s\n"
msgstr "enregistrement de base de confiance %lu : lseek a échoué : %s\n"
#: g10/tdbio.c:122 g10/tdbio.c:1420
#, c-format
msgid "trustdb rec %lu: write failed (n=%d): %s\n"
msgstr ""
"enregistrement de la base de confiance %lu : l'écriture a échoué (n=%d) : "
"%s\n"
#: g10/tdbio.c:232
msgid "trustdb transaction to large\n"
msgstr "transaction de base de confiance trop volumineuse\n"
#: g10/tdbio.c:402
#, c-format
msgid "%s: can't access: %s\n"
msgstr "%s : ne peut accéder : %s\n"
#: g10/ringedit.c:273 g10/tdbio.c:422
#, c-format
msgid "%s: can't create directory: %s\n"
msgstr "%s : ne peut créer le répertoire : %s\n"
#: g10/ringedit.c:279 g10/tdbio.c:425
#, c-format
msgid "%s: directory created\n"
msgstr "%s : répertoire créé\n"
#: g10/tdbio.c:429
#, c-format
msgid "%s: directory does not exist!\n"
msgstr "%s : le répertoire n'existe pas !\n"
#: g10/openfile.c:101 g10/openfile.c:165 g10/ringedit.c:1256 g10/tdbio.c:435
#, c-format
msgid "%s: can't create: %s\n"
msgstr "%s : ne peut créer : %s\n"
#: g10/tdbio.c:459
#, c-format
msgid "%s: failed to create version record: %s"
msgstr "%s : n'a pas pu créer un enregistrement de version : %s"
#: g10/tdbio.c:463
#, c-format
msgid "%s: invalid trust-db created\n"
msgstr "%s : base de confiance invalide créée\n"
#: g10/tdbio.c:465
#, c-format
msgid "%s: trust-db created\n"
msgstr "%s : base de confiance créée\n"
#: g10/tdbio.c:506
#, c-format
msgid "%s: invalid trust-db\n"
msgstr "%s : base de confiance invalide\n"
#: g10/tdbio.c:540
#, c-format
msgid "%s: failed to create hashtable: %s\n"
msgstr "%s : la création de la table de hachage a échoué : %s\n"
#: g10/tdbio.c:548
#, c-format
msgid "%s: error updating version record: %s\n"
msgstr ""
"%s : erreur pendant la mise à jour de l'enregistrement de version : %s\n"
#: g10/tdbio.c:564 g10/tdbio.c:603 g10/tdbio.c:628 g10/tdbio.c:1346
#: g10/tdbio.c:1373
#, c-format
msgid "%s: error reading version record: %s\n"
msgstr "%s : erreur pendant la lecture de l'enregistrement de version : %s\n"
#: g10/tdbio.c:577
#, c-format
msgid "%s: error writing version record: %s\n"
msgstr "%s : erreur pendant l'écriture de l'enregistrement de version : %s\n"
#: g10/tdbio.c:1053
#, c-format
msgid "trustdb: lseek failed: %s\n"
msgstr "base de confiance : « lseek() » a échoué : %s\n"
#: g10/tdbio.c:1061
#, c-format
msgid "trustdb: read failed (n=%d): %s\n"
msgstr "base de confiance : la lecture a échoué (n=%d) : %s\n"
#: g10/tdbio.c:1082
#, c-format
msgid "%s: not a trustdb file\n"
msgstr "%s : ce n'est pas un fichier de base de confiance\n"
#: g10/tdbio.c:1098
#, c-format
msgid "%s: version record with recnum %lu\n"
msgstr "%s : enregistrement de version avec un numéro %lu\n"
#: g10/tdbio.c:1103
#, c-format
msgid "%s: invalid file version %d\n"
msgstr "%s : version %d du fichier invalide\n"
#: g10/tdbio.c:1379
#, c-format
msgid "%s: error reading free record: %s\n"
msgstr "%s : erreur pendant la lecture de l'enregistrement libre : %s\n"
#: g10/tdbio.c:1387
#, c-format
msgid "%s: error writing dir record: %s\n"
msgstr ""
"%s : erreur pendant l'écriture de l'enregistrement de\n"
"répertoire : %s\n"
#: g10/tdbio.c:1397
#, c-format
msgid "%s: failed to zero a record: %s\n"
msgstr "%s : n'a pu mettre un enregistrement à zéro : %s\n"
#: g10/tdbio.c:1427
#, c-format
msgid "%s: failed to append a record: %s\n"
msgstr "%s : n'a pas pu ajouter un enregistrement : %s\n"
-#: g10/trustdb.c:134
+#: g10/trustdb.c:142
msgid "The trust DB is corrupted; please run \"gpgm --fix-trust-db\".\n"
msgstr ""
"La base de confiance est corrompue ; exécutez « gpgm --fix-trust-db ».\n"
-#: g10/trustdb.c:147
+#: g10/trustdb.c:155
#, c-format
msgid "trust record %lu, req type %d: read failed: %s\n"
msgstr ""
"enregistrement de confiance %lu, type de requête %d : la lecture a échoué : "
"%s\n"
-#: g10/trustdb.c:162
+#: g10/trustdb.c:170
#, c-format
msgid "trust record %lu, type %d: write failed: %s\n"
msgstr "enregistrement de confiance %lu, type %d : l'écriture a échoué : %s\n"
-#: g10/trustdb.c:176
+#: g10/trustdb.c:184
#, c-format
msgid "trust record %lu: delete failed: %s\n"
msgstr "enregistrement de confiance %lu : la suppression a échoué : %s\n"
-#: g10/trustdb.c:190
+#: g10/trustdb.c:198
#, c-format
msgid "trust db: sync failed: %s\n"
msgstr "base de confiance a échoué : la synchronisation a échoué : %s\n"
-#: g10/trustdb.c:319
+#: g10/trustdb.c:327
#, c-format
msgid "error reading dir record for LID %lu: %s\n"
msgstr ""
"erreur pendant la lecture de l'enregistrement de répertoire pour\n"
"le LID %lu : %s\n"
-#: g10/trustdb.c:326
+#: g10/trustdb.c:334
#, c-format
msgid "lid %lu: expected dir record, got type %d\n"
msgstr "lid %lu : enregistrement de répertoire attendu, a reçu le type %d\n"
-#: g10/trustdb.c:331
+#: g10/trustdb.c:339
#, c-format
msgid "no primary key for LID %lu\n"
msgstr "pas de clé principale pour le LID %lu\n"
-#: g10/trustdb.c:336
+#: g10/trustdb.c:344
#, c-format
msgid "error reading primary key for LID %lu: %s\n"
msgstr "erreur pendant la lecture de la clé principale pour le LID %lu : %s\n"
-#: g10/trustdb.c:412
+#: g10/trustdb.c:420
#, c-format
msgid "chained sigrec %lu has a wrong owner\n"
msgstr "l'enregistrement de signature %lu a un mauvais propriétaire\n"
-#: g10/trustdb.c:455
+#: g10/trustdb.c:463
#, c-format
msgid "'%s' is not a valid long keyID\n"
msgstr "'%s' n'est pas une identification longue de clé valide\n"
-#: g10/trustdb.c:490
+#: g10/trustdb.c:498
#, c-format
msgid "key %08lX: no public key for trusted key - skipped\n"
msgstr "clé %08lX : pas de clé publique pour la clé certifiée - ignorée\n"
-#: g10/trustdb.c:499 g10/trustdb.c:557
+#: g10/trustdb.c:507 g10/trustdb.c:565
#, c-format
msgid "key %08lX: can't put it into the trustdb\n"
msgstr "clé %08lX : ne peut être mise dans la base de confiance\n"
-#: g10/trustdb.c:504 g10/trustdb.c:563
+#: g10/trustdb.c:512 g10/trustdb.c:571
#, c-format
msgid "key %08lX: query record failed\n"
msgstr "clé %08lX : l'enregistrement de requête a échoué\n"
-#: g10/trustdb.c:509 g10/trustdb.c:572
+#: g10/trustdb.c:517 g10/trustdb.c:580
#, c-format
msgid "key %08lX: already in trusted key table\n"
msgstr "clé %08lX : déjà dans la table des clés certifiées\n"
-#: g10/trustdb.c:512 g10/trustdb.c:575
+#: g10/trustdb.c:520 g10/trustdb.c:583
#, c-format
msgid "key %08lX: accepted as trusted key.\n"
msgstr "clé %08lX : acceptée comme clé certifiée.\n"
-#: g10/trustdb.c:528
+#: g10/trustdb.c:536
#, c-format
msgid "NOTE: secret key %08lX is NOT protected.\n"
msgstr "NOTE : la clé secrète %08lX n'est PAS protégée.\n"
-#: g10/trustdb.c:540
+#: g10/trustdb.c:548
#, c-format
msgid "key %08lX: secret key without public key - skipped\n"
msgstr "clé %08lX : clé secrète sans clé publique - non prise en compte\n"
-#: g10/trustdb.c:547
+#: g10/trustdb.c:555
#, c-format
msgid "key %08lX: secret and public key don't match\n"
msgstr "clé %08lX : les clés secrète et publique ne correspondent pas\n"
-#: g10/trustdb.c:583
+#: g10/trustdb.c:591
#, c-format
msgid "enumerate secret keys failed: %s\n"
msgstr "l'énumération des clés secrètes a échoué : %s\n"
-#: g10/trustdb.c:766
+#: g10/trustdb.c:774
#, c-format
msgid "lid %lu: read dir record failed: %s\n"
msgstr "lid %lu : la lecture d'enregistrement de répertoire a échoué : %s\n"
-#: g10/trustdb.c:775
+#: g10/trustdb.c:783
#, c-format
msgid "lid %lu: read key record failed: %s\n"
msgstr "lid %lu : la lecture de l''enregistrement de clé a échoué : %s\n"
-#: g10/trustdb.c:785
+#: g10/trustdb.c:793
#, c-format
msgid "lid %lu: read uid record failed: %s\n"
msgstr "lid %lu : la lecture d'enregistrement d'uid a échoué : %s\n"
-#: g10/trustdb.c:794
+#: g10/trustdb.c:802
#, c-format
msgid "lid %lu: read pref record failed: %s\n"
msgstr "lid %lu : la lecture d'enregistrement de préférences a échoué : %s\n"
-#: g10/trustdb.c:804
+#: g10/trustdb.c:812
#, c-format
msgid "lid %lu: read sig record failed: %s\n"
msgstr "lid %lu : la lecture d'enregistrement de signature a échoué : %s\n"
-#: g10/trustdb.c:999
+#: g10/trustdb.c:1013
msgid "Ooops, no keys\n"
msgstr "Ooops, pas de clé\n"
-#: g10/trustdb.c:1003
+#: g10/trustdb.c:1017
msgid "Ooops, no user ids\n"
msgstr "Ooops, pas de nom d'utilisateur\n"
-#: g10/trustdb.c:1074 g10/trustdb.c:1092
+#: g10/trustdb.c:1088 g10/trustdb.c:1106
#, c-format
msgid "user '%s' read problem: %s\n"
msgstr "problème de lecture de l'utilisateur '%s' : %s\n"
-#: g10/trustdb.c:1077 g10/trustdb.c:1095
+#: g10/trustdb.c:1091 g10/trustdb.c:1109
#, c-format
msgid "user '%s' list problem: %s\n"
msgstr "problème de liste à l'utilisateur '%s' : %s\n"
-#: g10/trustdb.c:1085 g10/trustdb.c:1300
+#: g10/trustdb.c:1099 g10/trustdb.c:1346
#, c-format
msgid "user '%s' not found: %s\n"
msgstr "l'utilisateur '%s' n'a pas été trouvé : %s\n"
-#: g10/trustdb.c:1087 g10/trustdb.c:1302
+#: g10/trustdb.c:1101 g10/trustdb.c:1348
#, c-format
msgid "problem finding '%s' in trustdb: %s\n"
msgstr "problème de recherche de '%s' dans la base de confiance : %s\n"
-#: g10/trustdb.c:1090
+#: g10/trustdb.c:1104
#, c-format
msgid "user '%s' not in trustdb\n"
msgstr "l'utilisateur '%s' n'est pas dans la base de confiance\n"
-#: g10/trustdb.c:1125
+#: g10/trustdb.c:1139
#, c-format
msgid ""
"# List of assigned trustvalues, created %s\n"
"# (Use \"gpgm --import-ownertrust\" to restore them)\n"
msgstr ""
"# Liste des indices de confiance assignés, créée le %s\n"
"# (Utiliser « gpgm --import-ownertrust » pour les restaurer)\n"
-#: g10/trustdb.c:1131
+#: g10/trustdb.c:1145
msgid "directory record w/o primary key\n"
msgstr "enregistrement de répertoire sans clé principale\n"
-#: g10/trustdb.c:1138
+#: g10/trustdb.c:1152
#, c-format
msgid "error reading key record: %s\n"
msgstr "erreur pendant la lecture de l'enregistrement de clé : %s\n"
-#: g10/trustdb.c:1178
+#: g10/trustdb.c:1192
msgid "line too long\n"
msgstr "ligne trop longue\n"
-#: g10/trustdb.c:1186
+#: g10/trustdb.c:1200
msgid "error: missing colon\n"
msgstr "erreur : deux-points manquant\n"
-#: g10/trustdb.c:1191
+#: g10/trustdb.c:1205
msgid "error: invalid fingerprint\n"
msgstr "erreur : empreinte digitale invalide\n"
-#: g10/trustdb.c:1195
+#: g10/trustdb.c:1209
msgid "error: no ownertrust value\n"
msgstr "erreur : pas d'indice de confiance\n"
-#: g10/trustdb.c:1209
+#: g10/trustdb.c:1223
#, c-format
msgid "LID %lu: changing trust from %u to %u\n"
msgstr "LID %lu : changement de la confiance de %u vers %u\n"
-#: g10/trustdb.c:1212
+#: g10/trustdb.c:1226
#, c-format
msgid "LID %lu: setting trust to %u\n"
msgstr "LID %lu : la confiance est maintenant %u\n"
-#: g10/trustdb.c:1220
+#: g10/trustdb.c:1234
msgid "key not in trustdb, searching ring.\n"
msgstr "la clé n'est pas dans la base de confiance, recherche du porte-clés.\n"
-#: g10/trustdb.c:1223
+#: g10/trustdb.c:1237
#, c-format
msgid "key not in ring: %s\n"
msgstr "clé absente du porte-clés : %s\n"
-#: g10/trustdb.c:1227
+#: g10/trustdb.c:1241
msgid "Oops: key is now in trustdb???\n"
msgstr "Oops : la clé est maintenant dans la base de confiance ???\n"
#. update the ownertrust
-#: g10/trustdb.c:1232
+#: g10/trustdb.c:1246
#, c-format
msgid "insert trust record failed: %s\n"
msgstr "l'insertion d'enregistrement de confiance a échoué : %s\n"
#. error
-#: g10/trustdb.c:1238
+#: g10/trustdb.c:1252
#, c-format
msgid "error finding dir record: %s\n"
msgstr "erreur pendant la recherche de l'enregistrement de répertoire : %s\n"
-#: g10/trustdb.c:1305
+#: g10/trustdb.c:1351
#, c-format
msgid "user '%s' not in trustdb - inserting\n"
msgstr "l'utilisateur '%s' n'est pas dans la base de confiance - insertion\n"
-#: g10/trustdb.c:1308
+#: g10/trustdb.c:1354
#, c-format
msgid "failed to put '%s' into trustdb: %s\n"
msgstr "n'a pas pu insérer '%s' dans la base de confiance : %s\n"
-#: g10/trustdb.c:1355
+#: g10/trustdb.c:1404
#, c-format
msgid "%s: keyblock read problem: %s\n"
msgstr "%s : problème de lecture du bloc de clés : %s\n"
-#: g10/trustdb.c:1369
+#: g10/trustdb.c:1418
#, c-format
msgid "%s: update failed: %s\n"
msgstr "%s : la mise à jour a échoué : %s\n"
-#: g10/trustdb.c:1372
+#: g10/trustdb.c:1421
#, c-format
msgid "%s: updated\n"
msgstr "%s : mis à jour\n"
-#: g10/trustdb.c:1374
+#: g10/trustdb.c:1423
#, c-format
msgid "%s: okay\n"
msgstr "%s : OK\n"
-#: g10/trustdb.c:1389
+#: g10/trustdb.c:1438
#, c-format
msgid "lid %lu: dir record w/o key - skipped\n"
msgstr "lid %lu : enregistrement de répertoire sans clé - ignoré\n"
-#: g10/trustdb.c:1402
+#: g10/trustdb.c:1451
#, c-format
msgid "lid %lu: keyblock not found: %s\n"
msgstr "lid %lu : le bloc de clés n'a pas été trouvé : %s\n"
-#: g10/trustdb.c:1411 g10/trustdb.c:1480
+#: g10/trustdb.c:1460 g10/trustdb.c:1529
#, c-format
msgid "lid %lu: update failed: %s\n"
msgstr "lid %lu : la mise à jour a échoué: %s\n"
-#: g10/trustdb.c:1417 g10/trustdb.c:1486
+#: g10/trustdb.c:1466 g10/trustdb.c:1535
#, c-format
msgid "lid %lu: updated\n"
msgstr "lid %lu : mis à jour\n"
-#: g10/trustdb.c:1421 g10/trustdb.c:1490
+#: g10/trustdb.c:1470 g10/trustdb.c:1539
#, c-format
msgid "lid %lu: okay\n"
msgstr "lid %lu : OK\n"
-#: g10/trustdb.c:1428 g10/trustdb.c:1496
+#: g10/trustdb.c:1477 g10/trustdb.c:1545
#, c-format
msgid "%lu keys processed\n"
msgstr "%lu clés traitées\n"
-#: g10/trustdb.c:1430
+#: g10/trustdb.c:1479
#, c-format
msgid "\t%lu keys skipped\n"
msgstr "\t%lu clés ignorées\n"
-#: g10/trustdb.c:1432 g10/trustdb.c:1498
+#: g10/trustdb.c:1481 g10/trustdb.c:1547
#, c-format
msgid "\t%lu keys with errors\n"
msgstr "\t%lu clés avec erreurs\n"
-#: g10/trustdb.c:1434 g10/trustdb.c:1500
+#: g10/trustdb.c:1483 g10/trustdb.c:1549
#, c-format
msgid "\t%lu keys updated\n"
msgstr "\t%lu clés mises à jour\n"
-#: g10/trustdb.c:1464
+#: g10/trustdb.c:1513
#, c-format
msgid "lid ?: insert failed: %s\n"
msgstr "lid ? : l'insertion a échoué : %s\n"
-#: g10/trustdb.c:1469
+#: g10/trustdb.c:1518
#, c-format
msgid "lid %lu: insert failed: %s\n"
msgstr "lid %lu : l'insertion a échoué : %s\n"
-#: g10/trustdb.c:1475
+#: g10/trustdb.c:1524
#, c-format
msgid "lid %lu: inserted\n"
msgstr "lid %lu : inséré\n"
-#: g10/trustdb.c:1502
+#: g10/trustdb.c:1551
#, c-format
msgid "\t%lu keys inserted\n"
msgstr "\t%lu clés insérées\n"
-#: g10/trustdb.c:1505
+#: g10/trustdb.c:1554
#, c-format
msgid "enumerate keyblocks failed: %s\n"
msgstr "l'énumération des blocs de clés a échoué : %s\n"
-#: g10/trustdb.c:1550
+#: g10/trustdb.c:1599
#, c-format
msgid "check_trust: search dir record failed: %s\n"
msgstr ""
"check_trust : la recherche d'enregistrement de répertoire a échoué : %s\n"
-#: g10/trustdb.c:1557
+#: g10/trustdb.c:1606
#, c-format
msgid "key %08lX: insert trust record failed: %s\n"
msgstr "clé %08lX : l'insertion d'enregistrement de confiance a échoué : %s\n"
-#: g10/trustdb.c:1561
+#: g10/trustdb.c:1610
#, c-format
msgid "key %08lX.%lu: inserted into trustdb\n"
msgstr "clé %08lX.%lu : insérée dans la base de confiance\n"
-#: g10/trustdb.c:1569
+#: g10/trustdb.c:1618
#, c-format
msgid "key %08lX.%lu: created in future (time warp or clock problem)\n"
msgstr ""
"clé %08lX.%lu : créée dans le futur (voyage temporel ou\n"
"problème d'horloge)\n"
-#: g10/trustdb.c:1576
+#: g10/trustdb.c:1625
#, c-format
msgid "key %08lX.%lu: expired at %s\n"
msgstr "clé %08lX.%lu : a expiré le %s\n"
-#: g10/trustdb.c:1584
+#: g10/trustdb.c:1633
#, c-format
msgid "key %08lX.%lu: trust check failed: %s\n"
msgstr "clé %08lX.%lu : la vérification de confiance a échoué: %s\n"
-#: g10/trustdb.c:1753 g10/trustdb.c:1782 g10/trustdb.c:2521
+#: g10/trustdb.c:1820 g10/trustdb.c:1849 g10/trustdb.c:2588
msgid "WARNING: can't yet handle long pref records\n"
msgstr ""
"ATTENTION : les enregistrements de préférences longs ne sont pas encore\n"
"supportés\n"
-#: g10/trustdb.c:1804
+#: g10/trustdb.c:1871
#, c-format
msgid "get_dir_record: search_record failed: %s\n"
msgstr "get_dir_record : search_record a échoué : %s\n"
-#: g10/trustdb.c:1867
+#: g10/trustdb.c:1934
#, c-format
msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but marked as checked\n"
msgstr ""
"NOTE : l'enregistrement de signature %lu[%d] est dans la liste d'aide\n"
"de %lu mais marqué comme vérifié\n"
-#: g10/trustdb.c:1871
+#: g10/trustdb.c:1938
#, c-format
msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but not marked\n"
msgstr ""
"NOTE : l'enregistrement de signature %lu[%d] est dans la liste d'aide\n"
"de %lu mais n'est pas marqué\n"
#. we need the dir record
-#: g10/trustdb.c:1878
+#: g10/trustdb.c:1945
#, c-format
msgid "sig rec %lu[%d] in hintlist of %lu does not point to a dir record\n"
msgstr ""
"l'enregistrement de signature %lu[%d] dans la liste d'aide de %lu\n"
"ne pointe pas vers un enregistrement de répertoire\n"
-#: g10/trustdb.c:1884
+#: g10/trustdb.c:1951
#, c-format
msgid "lid %lu: no primary key\n"
msgstr "lid %lu : pas de clé primaire\n"
-#: g10/trustdb.c:1917
+#: g10/trustdb.c:1984
#, c-format
msgid "lid %lu: user id not found in keyblock\n"
msgstr "lid %lu : utilisateur non trouvé dans le bloc de clés\n"
-#: g10/trustdb.c:1921
+#: g10/trustdb.c:1988
#, c-format
msgid "lid %lu: user id without signature\n"
msgstr "lid %lu : utilisateur sans signature\n"
-#: g10/trustdb.c:1928
+#: g10/trustdb.c:1995
#, c-format
msgid "lid %lu: self-signature in hintlist\n"
msgstr "lid %lu : auto-signature dans la liste d'aide\n"
-#: g10/trustdb.c:1939 g10/trustdb.c:2658 g10/trustdb.c:2742
+#: g10/trustdb.c:2006 g10/trustdb.c:2725 g10/trustdb.c:2809
msgid "Valid certificate revocation"
msgstr "Certificat de révocation valide"
-#: g10/trustdb.c:1940 g10/trustdb.c:2659 g10/trustdb.c:2743
+#: g10/trustdb.c:2007 g10/trustdb.c:2726 g10/trustdb.c:2810
msgid "Good certificate"
msgstr "Bon certificat"
-#: g10/trustdb.c:1949
+#: g10/trustdb.c:2016
msgid "very strange: no public key\n"
msgstr "très étrange : pas de clé publique\n"
-#: g10/trustdb.c:1997
+#: g10/trustdb.c:2064
#, c-format
msgid "hintlist %lu[%d] of %lu does not point to a dir record\n"
msgstr ""
"la liste d'aide de %lu[%d] de %lu ne pointe pas vers un enregistrement\n"
"de répertoire\n"
-#: g10/trustdb.c:2003
+#: g10/trustdb.c:2070
#, c-format
msgid "lid %lu does not have a key\n"
msgstr "la lid %lu n'a pas de clé\n"
-#: g10/trustdb.c:2013
+#: g10/trustdb.c:2080
#, c-format
msgid "lid %lu: can't get keyblock: %s\n"
msgstr "lid %lu: ne peut obtenir le bloc de clés: %s\n"
-#: g10/trustdb.c:2070 g10/trustdb.c:2984
+#: g10/trustdb.c:2137 g10/trustdb.c:3051
#, c-format
msgid "tdbio_search_dir failed: %s\n"
msgstr "tdbio_search_dir a échoué : %s\n"
-#: g10/trustdb.c:2223
+#: g10/trustdb.c:2290
#, c-format
msgid "key %08lX.%lu: Good subkey binding\n"
msgstr "clé %08lX.%lu : bonne liaison avec la sous-clé\n"
-#: g10/trustdb.c:2229 g10/trustdb.c:2271
+#: g10/trustdb.c:2296 g10/trustdb.c:2338
#, c-format
msgid "key %08lX.%lu: Invalid subkey binding: %s\n"
msgstr "clé %08lX.%lu : liaison avec la sous-clé invalide : %s\n"
-#: g10/trustdb.c:2244
+#: g10/trustdb.c:2311
#, c-format
msgid "key %08lX.%lu: Valid key revocation\n"
msgstr "clé %08lX.%lu : révocation de clé valide\n"
-#: g10/trustdb.c:2250
+#: g10/trustdb.c:2317
#, c-format
msgid "key %08lX.%lu: Invalid key revocation: %s\n"
msgstr "clé %08lX.%lu : révocation de sous-clé invalide : %s\n"
-#: g10/trustdb.c:2265
+#: g10/trustdb.c:2332
#, c-format
msgid "key %08lX.%lu: Valid subkey revocation\n"
msgstr "clé %08lX.%lu : révocation de sous-clé valide\n"
-#: g10/trustdb.c:2365
+#: g10/trustdb.c:2432
msgid "Good self-signature"
msgstr "Bonne auto-signature"
-#: g10/trustdb.c:2376
+#: g10/trustdb.c:2443
msgid "Invalid self-signature"
msgstr "Auto-signature invalide"
-#: g10/trustdb.c:2386
+#: g10/trustdb.c:2453
msgid "Valid user ID revocation skipped due to a newer self signature\n"
msgstr ""
"La révocation valide de nom d'utilisateur a été ignorée car l'auto-\n"
"signature est plus récente\n"
-#: g10/trustdb.c:2393
+#: g10/trustdb.c:2460
msgid "Valid user ID revocation\n"
msgstr "Révocation de nom d'utilisateur valide\n"
-#: g10/trustdb.c:2400
+#: g10/trustdb.c:2467
msgid "Invalid user ID revocation"
msgstr "Révocation de nom d'utilisateur invalide"
-#: g10/trustdb.c:2484
+#: g10/trustdb.c:2551
msgid "Too many preferences"
msgstr "Trop de préférences"
-#: g10/trustdb.c:2498
+#: g10/trustdb.c:2565
msgid "Too many preference items"
msgstr "Trop d'items de préférence"
-#: g10/trustdb.c:2637
+#: g10/trustdb.c:2704
msgid "Duplicated certificate - deleted"
msgstr "Certificat dupliqué - enlevé"
-#: g10/trustdb.c:2670
+#: g10/trustdb.c:2737
msgid "Hmmm, public key lost?"
msgstr "Hmmm, clé publique perdue ?"
-#: g10/trustdb.c:2680 g10/trustdb.c:2763
+#: g10/trustdb.c:2747 g10/trustdb.c:2830
msgid "Invalid certificate revocation"
msgstr "Révocation de certificat invalide"
-#: g10/trustdb.c:2681 g10/trustdb.c:2764
+#: g10/trustdb.c:2748 g10/trustdb.c:2831
msgid "Invalid certificate"
msgstr "Certificat invalide"
-#: g10/trustdb.c:2696
+#: g10/trustdb.c:2763
#, c-format
msgid "uid %08lX.%lu/%02X%02X: has shadow dir %lu but is not yet marked.\n"
msgstr ""
"uid %08lX.%lu/%02X%02X : possède une ombre %lu mais n'est pas encore\n"
"marqué.\n"
-#: g10/trustdb.c:2710
+#: g10/trustdb.c:2777
#, c-format
msgid "sig record %lu[%d] points to wrong record.\n"
msgstr ""
"l'enregistrement de signature %lu[%d] pointe vers le mauvais\n"
"enregistrement de répertoire\n"
#. that should never happen
-#: g10/trustdb.c:2954
+#: g10/trustdb.c:3021
#, c-format
msgid "insert_trust_record: keyblock not found: %s\n"
msgstr "insert_trust_record : bloc de clés non trouvé : %s\n"
-#: g10/trustdb.c:2972
+#: g10/trustdb.c:3039
msgid "did not use primary key for insert_trust_record()\n"
msgstr "n'a pas utilisé la clé principale pour « insert_trust_record() »\n"
#: g10/ringedit.c:293
#, c-format
msgid "%s: can't create keyring: %s\n"
msgstr "%s : ne peut créer le porte-clés : %s\n"
#: g10/ringedit.c:299 g10/ringedit.c:1264
#, c-format
msgid "%s: keyring created\n"
msgstr "%s : porte-clés créé\n"
#: g10/ringedit.c:1449
msgid "WARNING: 2 files with confidential information exists.\n"
msgstr ""
"ATTENTION : 2 fichiers avec des informations confidentielles existent.\n"
#: g10/ringedit.c:1450
#, c-format
msgid "%s is the unchanged one\n"
msgstr "%s est le fichier original\n"
#: g10/ringedit.c:1451
#, c-format
msgid "%s is the new one\n"
msgstr "%s est le nouveau\n"
#: g10/ringedit.c:1452
msgid "Please fix this possible security flaw\n"
msgstr "Réparez ce problème de sécurité possible\n"
#: g10/skclist.c:94
#, c-format
msgid "skipped '%s': %s\n"
msgstr "'%s' a été ignoré : %s\n"
#: g10/skclist.c:100
#, c-format
msgid ""
"skipped '%s': this is a PGP generated ElGamal key which is not secure for "
"signatures!\n"
msgstr ""
"'%s' a été ignorée : c'est une clé ElGamal générée par PGP qui n'est pas\n"
"sûre pour les signatures !\n"
#. do not overwrite
#: g10/openfile.c:58
#, c-format
msgid "File '%s' exists. "
msgstr "Le fichier '%s' existe. "
#: g10/openfile.c:60
msgid "Overwrite (y/N)? "
msgstr "Réécrire (o/N)? "
#: g10/openfile.c:85
msgid "writing to stdout\n"
msgstr "écriture vers la sortie standard\n"
#: g10/openfile.c:134
#, c-format
msgid "assuming signed data in '%s'\n"
msgstr "les données signées sont supposées être dans '%s'\n"
#: g10/openfile.c:181
#, c-format
msgid "%s: new options file created\n"
msgstr "%s : nouveau fichier d'options créé\n"
#: g10/encr-data.c:59
#, c-format
msgid "%s encrypted data\n"
msgstr "données chiffrées avec %s\n"
#: g10/encr-data.c:61
#, c-format
msgid "encrypted with unknown algorithm %d\n"
msgstr "chiffré avec l'algorithme inconnu %d\n"
#: g10/encr-data.c:74
msgid ""
"WARNING: Message was encrypted with a weak key in the symmetric cipher.\n"
msgstr ""
"ATTENTION : Le message a été chiffré avec une mauvaise clé pendant le\n"
"chiffrement symétrique.\n"
#: g10/seskey.c:52
msgid "weak key created - retrying\n"
msgstr "mauvaise clé générée - nouvel essai\n"
#: g10/seskey.c:57
#, c-format
msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n"
msgstr ""
"ne peut éviter une mauvaise clé pour le chiffrement symétrique : \n"
"%d essais ont eu lieu!\n"
#. begin of list
#: g10/helptext.c:48
msgid "edit_ownertrust.value"
msgstr ""
"C'est à vous d'assigner une valeur ici ; cette valeur ne sera jamais\n"
"exportée à une tierce personne. Nous en avons besoin pour créer le\n"
"réseau de confiance (web-of-trust) ; cela n'a rien à voir avec le\n"
"réseau de certificats (créé implicitement)"
#: g10/helptext.c:54
msgid "revoked_key.override"
msgstr ""
"Si vous voulez utiliser cette clé révoquée quand-même, répondez « oui »."
#: g10/helptext.c:58
msgid "untrusted_key.override"
msgstr ""
"Si vous voulez utiliser cette clé peu sûre quand-même, répondez « oui »."
#: g10/helptext.c:62
msgid "pklist.user_id.enter"
msgstr "Entrez l'adresse de la personne à qui vous voulez envoyer le message."
#: g10/helptext.c:66
msgid "keygen.algo"
msgstr "Sélectionnez l'algorithme à utiliser:"
#: g10/helptext.c:82
msgid "keygen.algo.elg_se"
msgstr ""
"Bien que ces clés soient définies dans la RFC2440 elles ne sont pas\n"
"conseillées car tous les programmes ne les supportent pas et les signatures\n"
"créées avec elles sont plutôt longues et très lentes à vérifier."
#: g10/helptext.c:89
msgid "keygen.size"
msgstr ""
#: g10/helptext.c:93
msgid "keygen.size.huge.okay"
msgstr ""
#: g10/helptext.c:98
msgid "keygen.size.large.okay"
msgstr ""
#: g10/helptext.c:103
msgid "keygen.valid"
msgstr ""
#: g10/helptext.c:107
msgid "keygen.valid.okay"
msgstr ""
#: g10/helptext.c:112
msgid "keygen.name"
msgstr ""
#: g10/helptext.c:117
msgid "keygen.email"
msgstr ""
#: g10/helptext.c:121
msgid "keygen.comment"
msgstr ""
#: g10/helptext.c:126
msgid "keygen.userid.cmd"
msgstr ""
"N pour changer le nom.\n"
"C pour changer le commentaire.\n"
"E pour changer l'adresse e-mail.\n"
"O pour continuer à générer la clé.\n"
"Q pour arrêter de générer de clé."
#: g10/helptext.c:135
msgid "keygen.sub.okay"
msgstr "Répondez « oui » (ou simplement « o ») pour générer la sous-clé"
#: g10/helptext.c:139
msgid "sign_uid.okay"
msgstr ""
#: g10/helptext.c:144
msgid "change_passwd.empty.okay"
msgstr ""
#: g10/helptext.c:149
msgid "keyedit.cmd"
msgstr "Entrez « aide » pour voir la liste des commandes."
#: g10/helptext.c:153
msgid "keyedit.save.okay"
msgstr ""
#: g10/helptext.c:158
msgid "keyedit.cancel.okay"
msgstr ""
#: g10/helptext.c:162
msgid "keyedit.sign_all.okay"
msgstr ""
#: g10/helptext.c:166
msgid "keyedit.remove.uid.okay"
msgstr ""
#: g10/helptext.c:171
msgid "keyedit.remove.subkey.okay"
msgstr ""
#: g10/helptext.c:175
msgid "passphrase.enter"
msgstr ""
"Entrez le mot de passe ; c'est une phrase secrète \n"
" Blurb, blurb,.... "
#: g10/helptext.c:182
msgid "passphrase.repeat"
msgstr ""
"Répétez le dernier mot de passe, pour être sûr de ce que vous avez tapé."
#: g10/helptext.c:186
msgid "detached_signature.filename"
msgstr ""
#: g10/helptext.c:190
msgid "openfile.overwrite.okay"
msgstr ""
#: g10/helptext.c:204
msgid "No help available"
msgstr "Pas d'aide disponible"
#: g10/helptext.c:216
#, c-format
msgid "No help available for '%s'"
msgstr "Pas d'aide disponible pour '%s'"
-
diff --git a/po/it.po b/po/it.po
index 752a31a7f..147b1e0a8 100644
--- a/po/it.po
+++ b/po/it.po
@@ -1,3066 +1,3080 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) 1998 Free Software Foundation, Inc.
# Marco d'Itri <md@linux.it>, 1998.
#
msgid ""
msgstr ""
"Project-Id-Version: gnupg-0.4.3\n"
-"POT-Creation-Date: 1998-12-10 20:11+0100\n"
+"POT-Creation-Date: 1998-12-17 18:30+0100\n"
"PO-Revision-Date: 1998-11-09 16:19+01:00\n"
"Last-Translator: Marco d'Itri <md@linux.it>\n"
"Language-Team: Italian <it@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-1\n"
"Content-Transfer-Encoding: 8bit\n"
#: util/secmem.c:77
msgid "Warning: using insecure memory!\n"
msgstr "Attenzione: si sta usando memoria insicura!\n"
#: util/miscutil.c:143
msgid "yes"
msgstr "sì"
#: util/miscutil.c:144
msgid "yY"
msgstr "sS"
#: util/errors.c:54
msgid "General error"
msgstr "Errore generale"
#: util/errors.c:55
msgid "Unknown packet type"
msgstr "Tipo del pacchetto sconosciuto"
#: util/errors.c:56
msgid "Unknown version"
msgstr "Versione sconosciuta"
#: util/errors.c:57
msgid "Unknown pubkey algorithm"
msgstr "Algoritmo della chiave pubblica sconosciuto"
#: util/errors.c:58
msgid "Unknown digest algorithm"
msgstr "Algoritmo del digest sconosciuto"
#: util/errors.c:59
msgid "Bad public key"
msgstr "Chiave pubblica errata o danneggiata"
#: util/errors.c:60
msgid "Bad secret key"
msgstr "Chiave segreta errata o danneggiata"
#: util/errors.c:61
msgid "Bad signature"
msgstr "Firma errata o danneggiata"
#: util/errors.c:62
msgid "Checksum error"
msgstr "Checksum errato"
#: util/errors.c:63
msgid "Bad passphrase"
msgstr "Passphrase errata"
#: util/errors.c:64
msgid "Public key not found"
msgstr "Chiave pubblica non trovata"
#: util/errors.c:65
msgid "Unknown cipher algorithm"
msgstr "Algoritmo di cifratura sconosciuto"
#: util/errors.c:66
msgid "Can't open the keyring"
msgstr "Impossibile aprire il portachiavi"
#: util/errors.c:67
msgid "Invalid packet"
msgstr "Pacchetto non valido"
#: util/errors.c:68
msgid "Invalid armor"
msgstr "Armatura non valida"
#: util/errors.c:69
msgid "No such user id"
msgstr "User id inesistente"
#: util/errors.c:70
msgid "Secret key not available"
msgstr "La chiave segreta non è disponibile."
#: util/errors.c:71
msgid "Wrong secret key used"
msgstr "È stata usata la chiave segreta sbagliata"
#: util/errors.c:72
msgid "Not supported"
msgstr "Non gestito"
#: util/errors.c:73
msgid "Bad key"
msgstr "Chiave danneggiata"
#: util/errors.c:74
msgid "File read error"
msgstr "Errore durante la lettura del file"
#: util/errors.c:75
msgid "File write error"
msgstr "Errore durante la scrittura del file"
#: util/errors.c:76
msgid "Unknown compress algorithm"
msgstr "Algoritmo di compressione sconosciuto"
#: util/errors.c:77
msgid "File open error"
msgstr "Errore durante l'apertura del file"
#: util/errors.c:78
msgid "File create error"
msgstr "Errore durante la creazione del file"
#: util/errors.c:79
msgid "Invalid passphrase"
msgstr "Passphrase non valida"
#: util/errors.c:80
msgid "Unimplemented pubkey algorithm"
msgstr "Algoritmo della chiave pubblica non implementato"
#: util/errors.c:81
msgid "Unimplemented cipher algorithm"
msgstr "Algoritmo di cifratura non implementato"
#: util/errors.c:82
msgid "Unknown signature class"
msgstr "Classe della firma sconosciuta."
#: util/errors.c:83
msgid "Trust database error"
msgstr "Errore nel database della fiducia"
#: util/errors.c:84
msgid "Bad MPI"
msgstr "MPI danneggiato"
#: util/errors.c:85
msgid "Resource limit"
msgstr "Limite della risorsa"
#: util/errors.c:86
msgid "Invalid keyring"
msgstr "Portachiavi non valido"
#: util/errors.c:87
msgid "Bad certificate"
msgstr "Certificato danneggiato"
#: util/errors.c:88
msgid "Malformed user id"
msgstr "User id malformato"
#: util/errors.c:89
msgid "File close error"
msgstr "Errore durante la chiusura del file"
#: util/errors.c:90
msgid "File rename error"
msgstr "Errore durante la rinominazione del file"
#: util/errors.c:91
msgid "File delete error"
msgstr "Errore durante la cancellazione del file"
#: util/errors.c:92
msgid "Unexpected data"
msgstr "Dati inaspettati"
#: util/errors.c:93
msgid "Timestamp conflict"
msgstr "Date in conflitto"
#: util/errors.c:94
msgid "Unusable pubkey algorithm"
msgstr "Algoritmo della chiave pubblica non utilizzabile"
#: util/errors.c:95
msgid "File exists"
msgstr "Il file esiste"
#: util/errors.c:96
msgid "Weak key"
msgstr "Chiave debole"
#: util/logger.c:178
#, c-format
msgid "... this is a bug (%s:%d:%s)\n"
msgstr "... questo è un bug (%s:%d:%s)\n"
#: util/logger.c:184
#, c-format
msgid "you found a bug ... (%s:%d)\n"
msgstr "Hai trovato un bug... (%s:%d)\n"
-#: cipher/random.c:412
+#: cipher/random.c:406
#, fuzzy
msgid "WARNING: using insecure random number generator!!\n"
msgstr ""
"Attenzione: si sta usando un generatore di numeri casuali non sicuro!!\n"
-#: cipher/random.c:413
+#: cipher/random.c:407
msgid ""
"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"
msgstr ""
"Il generatore di numeri casuali è solo un ripiego per fare\n"
"compilare il programma - non è assolutamente un RNG forte!\n"
-#: cipher/rndlinux.c:116
+#: cipher/rndlinux.c:118
#, c-format
msgid ""
"\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"
msgstr ""
"\n"
"Non ci sono abbastanza byte casuali disponibili. Per favore fai qualche\n"
"altra cosa per dare all'OS la possibilità di raccogliere altra entropia!\n"
"(Servono ancora %d altri byte)\n"
-#: g10/g10.c:159
+#: g10/g10.c:160
msgid ""
"@Commands:\n"
" "
msgstr ""
"@Comandi:\n"
" "
-#: g10/g10.c:162
+#: g10/g10.c:163
msgid "|[file]|make a signature"
msgstr "|[file]|fai una firma"
-#: g10/g10.c:163
+#: g10/g10.c:164
msgid "|[file]|make a clear text signature"
msgstr "|[file]|fai una firma mantenendo il testo in chiaro"
-#: g10/g10.c:164
+#: g10/g10.c:165
msgid "make a detached signature"
msgstr "fai una firma separata"
-#: g10/g10.c:165
+#: g10/g10.c:166
msgid "encrypt data"
msgstr "cifra dati"
-#: g10/g10.c:166
+#: g10/g10.c:167
msgid "encryption only with symmetric cipher"
msgstr "cifra solo con un cifrario simmetrico"
-#: g10/g10.c:167
+#: g10/g10.c:168
msgid "store only"
msgstr "immagazzina soltanto"
-#: g10/g10.c:168
+#: g10/g10.c:169
msgid "decrypt data (default)"
msgstr "decifra dati (predefinito)"
-#: g10/g10.c:169
+#: g10/g10.c:170
msgid "verify a signature"
msgstr "verifica una firma"
-#: g10/g10.c:171
+#: g10/g10.c:172
msgid "list keys"
msgstr "elenca le chiavi"
-#: g10/g10.c:172
+#: g10/g10.c:173
msgid "list keys and signatures"
msgstr "elenca le chiavi e le firme"
-#: g10/g10.c:173
+#: g10/g10.c:174
msgid "check key signatures"
msgstr "controlla le firme delle chiavi"
-#: g10/g10.c:174
+#: g10/g10.c:175
msgid "list keys and fingerprints"
msgstr "elenca le chiavi e le impronte digitali"
-#: g10/g10.c:175
+#: g10/g10.c:176
msgid "list secret keys"
msgstr "elenca le chiavi segrete"
-#: g10/g10.c:177
+#: g10/g10.c:178
msgid "generate a new key pair"
msgstr "genera una nuova coppia di chiavi"
-#: g10/g10.c:179
+#: g10/g10.c:180
msgid "remove key from the public keyring"
msgstr "rimuove una chiave dal portachiavi pubblico"
-#: g10/g10.c:181
+#: g10/g10.c:182
msgid "sign or edit a key"
msgstr "firma o modifica una chiave"
-#: g10/g10.c:182
+#: g10/g10.c:183
msgid "generate a revocation certificate"
msgstr "genera un certificato di revoca"
-#: g10/g10.c:184
+#: g10/g10.c:185
msgid "export keys"
msgstr "esporta delle chiavi"
-#: g10/g10.c:187
+#: g10/g10.c:188
msgid "import/merge keys"
msgstr "importa/aggiungi delle chiavi"
-#: g10/g10.c:189
+#: g10/g10.c:190
msgid "list only the sequence of packets"
msgstr "elenca solo la sequenza dei pacchetti"
-#: g10/g10.c:192
+#: g10/g10.c:193
msgid "export the ownertrust values"
msgstr "esporta i valori di fiducia"
-#: g10/g10.c:194
+#: g10/g10.c:195
msgid "import ownertrust values"
msgstr "importa i valori di fiducia"
-#: g10/g10.c:196
+#: g10/g10.c:197
msgid "|[NAMES]|update the trust database"
msgstr "|[NAMES]|controlla il database della fiducia"
-#: g10/g10.c:198
+#: g10/g10.c:199
msgid "|[NAMES]|check the trust database"
msgstr "|[NAMES]|controlla il database della fiducia"
-#: g10/g10.c:199
+#: g10/g10.c:200
msgid "fix a corrupted trust database"
msgstr "ripara un database della fiducia rovinato"
-#: g10/g10.c:200
+#: g10/g10.c:201
msgid "De-Armor a file or stdin"
msgstr "rimuovi l'armatura a un file o a stdin"
-#: g10/g10.c:201
+#: g10/g10.c:202
msgid "En-Armor a file or stdin"
msgstr "crea l'armatura a un file o a stdin"
-#: g10/g10.c:202
+#: g10/g10.c:203
msgid "|algo [files]|print message digests"
msgstr "|algo [files]|stampa tutti i message digests"
-#: g10/g10.c:203
+#: g10/g10.c:204
msgid "print all message digests"
msgstr "stampa tutti i message digests"
-#: g10/g10.c:210
+#: g10/g10.c:211
msgid ""
"@\n"
"Options:\n"
" "
msgstr ""
"@\n"
"Opzioni:\n"
" "
-#: g10/g10.c:212
+#: g10/g10.c:213
msgid "create ascii armored output"
msgstr "crea un output ascii con armatura"
-#: g10/g10.c:214
+#: g10/g10.c:215
msgid "use this user-id to sign or decrypt"
msgstr "usa questo user-id per firmare o decifrare"
-#: g10/g10.c:215
+#: g10/g10.c:216
msgid "use this user-id for encryption"
msgstr "usa questo user-id per cifrare"
-#: g10/g10.c:216
+#: g10/g10.c:217
msgid "|N|set compress level N (0 disables)"
msgstr "|N|imposta il livello di compressione (0 disabilita)"
-#: g10/g10.c:218
+#: g10/g10.c:219
msgid "use canonical text mode"
msgstr "usa il modo testo canonico"
-#: g10/g10.c:220
+#: g10/g10.c:221
msgid "use as output file"
msgstr "usa come file di output"
-#: g10/g10.c:221
+#: g10/g10.c:222
msgid "verbose"
msgstr "prolisso"
-#: g10/g10.c:222
+#: g10/g10.c:223
msgid "be somewhat more quiet"
msgstr "meno prolisso"
-#: g10/g10.c:223
+#: g10/g10.c:224
msgid "force v3 signatures"
msgstr "forza l'uso di firme v3"
#. { oDryRun, "dry-run", 0, N_("do not make any changes") },
-#: g10/g10.c:225
+#: g10/g10.c:226
msgid "batch mode: never ask"
msgstr "modo batch: non fare domande"
-#: g10/g10.c:226
+#: g10/g10.c:227
msgid "assume yes on most questions"
msgstr "assumi \"sì\" a quasi tutte le domande"
-#: g10/g10.c:227
+#: g10/g10.c:228
msgid "assume no on most questions"
msgstr "assumi \"no\" a quasi tutte le domande"
-#: g10/g10.c:228
+#: g10/g10.c:229
msgid "add this keyring to the list of keyrings"
msgstr "aggiungi questo portachiavi alla lista"
-#: g10/g10.c:229
+#: g10/g10.c:230
msgid "add this secret keyring to the list"
msgstr "aggiungi questo portachiavi segreto alla lista"
-#: g10/g10.c:230
+#: g10/g10.c:231
msgid "|NAME|use NAME as default secret key"
msgstr "|NAME|usa NAME come chiave segreta predefinita"
-#: g10/g10.c:231
+#: g10/g10.c:232
#, fuzzy
msgid "|NAME|set terminal charset to NAME"
msgstr "|NAME|usa l'algoritmo di cifratura NOME"
-#: g10/g10.c:232
+#: g10/g10.c:233
msgid "read options from file"
msgstr "leggi le opzioni dal file"
-#: g10/g10.c:234
+#: g10/g10.c:235
msgid "set debugging flags"
msgstr "imposta i flag di debugging"
-#: g10/g10.c:235
+#: g10/g10.c:236
msgid "enable full debugging"
msgstr "abilita il debugging completo"
-#: g10/g10.c:236
+#: g10/g10.c:237
msgid "|FD|write status info to this FD"
msgstr "|FD|scrivi le informazioni di stato su questo fd"
-#: g10/g10.c:237
+#: g10/g10.c:238
msgid "do not write comment packets"
msgstr "non scrivere pacchetti di commento"
-#: g10/g10.c:238
+#: g10/g10.c:239
msgid "(default is 1)"
msgstr "(predefinito è 1)"
-#: g10/g10.c:239
+#: g10/g10.c:240
msgid "(default is 3)"
msgstr "(predefinito è 3)"
-#: g10/g10.c:241
+#: g10/g10.c:242
msgid "|KEYID|ulimately trust this key"
msgstr ""
-#: g10/g10.c:242
+#: g10/g10.c:243
msgid "|FILE|load extension module FILE"
msgstr "|FILE|carica il modulo di estensione FILE"
-#: g10/g10.c:243
+#: g10/g10.c:244
msgid "emulate the mode described in RFC1991"
msgstr "emula il modo descritto nel RFC1991"
-#: g10/g10.c:244
+#: g10/g10.c:245
msgid "|N|use passphrase mode N"
msgstr "|N|usa il modo N per la passphrase"
-#: g10/g10.c:246
+#: g10/g10.c:247
msgid "|NAME|use message digest algorithm NAME for passphrases"
msgstr "|NAME|usa l'algoritmo di message digest NOME"
-#: g10/g10.c:248
+#: g10/g10.c:249
msgid "|NAME|use cipher algorithm NAME for passphrases"
msgstr "|NAME|usa l'alg. di cifratura NOME per le passphrase"
-#: g10/g10.c:250
+#: g10/g10.c:251
msgid "|NAME|use cipher algorithm NAME"
msgstr "|NAME|usa l'algoritmo di cifratura NOME"
-#: g10/g10.c:251
+#: g10/g10.c:252
msgid "|NAME|use message digest algorithm NAME"
msgstr "|NAME|usa l'algoritmo di message digest NOME"
-#: g10/g10.c:252
+#: g10/g10.c:253
msgid "|N|use compress algorithm N"
msgstr "|N|usa l'algoritmo di compressione N"
-#: g10/g10.c:253
+#: g10/g10.c:254
msgid "throw keyid field of encrypted packets"
msgstr "elimina il campo keyid dei pacchetti crittografati"
-#: g10/g10.c:261
+#: g10/g10.c:262
msgid ""
"@\n"
"Examples:\n"
"\n"
" -se -r Bob [file] sign and encrypt for user Bob\n"
" --clearsign [file] make a clear text signature\n"
" --detach-sign [file] make a detached signature\n"
" --list-keys [names] show keys\n"
" --fingerprint [names] show fingerprints\n"
msgstr ""
"@\n"
"Esempi:\n"
"\n"
" -se -r Bob [file] firma e cifra per l'utente Bob\n"
" --clearsign [file] fai una firma mantenendo il testo in chiaro\n"
" --detach-sign [file] fai una firma separata\n"
" --list-keys [nomi] mostra le chiavi\n"
" --fingerprint [nomi] mostra le impronte digitali\n"
-#: g10/g10.c:339
+#: g10/g10.c:341
msgid "Please report bugs to <gnupg-bugs@gnu.org>.\n"
msgstr "Per favore segnala i bug a <gnupg-bugs@gnu.org>.\n"
-#: g10/g10.c:344
+#: g10/g10.c:346
msgid "Usage: gpgm [options] [files] (-h for help)"
msgstr "Uso: gpgm [opzioni] [file] (-h per l'aiuto)"
-#: g10/g10.c:346
+#: g10/g10.c:348
msgid "Usage: gpg [options] [files] (-h for help)"
msgstr "Uso: gpg [opzioni] [file] (-h per l'aiuto)"
-#: g10/g10.c:351
+#: g10/g10.c:353
msgid ""
"Syntax: gpgm [options] [files]\n"
"GnuPG maintenance utility\n"
msgstr ""
"Sintassi: gpgm [opzioni] [file]\n"
"Utility di manutenzione di GnuPG\n"
-#: g10/g10.c:354
+#: g10/g10.c:356
msgid ""
"Syntax: gpg [options] [files]\n"
"sign, check, encrypt or decrypt\n"
"default operation depends on the input data\n"
msgstr ""
"Sintassi: gpg [opzioni] [file]\n"
"firma, controlla, cifra o decifra\n"
"l'operazione predefinita dipende dai dati di input\n"
-#: g10/g10.c:360
+#: g10/g10.c:362
msgid ""
"\n"
"Supported algorithms:\n"
msgstr ""
"\n"
"Algoritmi gestiti:\n"
-#: g10/g10.c:435
+#: g10/g10.c:437
msgid "usage: gpgm [options] "
msgstr "uso: gpgm [options] "
-#: g10/g10.c:437
+#: g10/g10.c:439
msgid "usage: gpg [options] "
msgstr "uso: gpg [options] "
-#: g10/g10.c:478
+#: g10/g10.c:480
msgid "conflicting commands\n"
msgstr "comandi in conflitto\n"
-#: g10/g10.c:616
+#: g10/g10.c:618
#, fuzzy, c-format
msgid "NOTE: no default option file '%s'\n"
msgstr "nota: nessun file con opzioni predefinite '%s'\n"
-#: g10/g10.c:620
+#: g10/g10.c:622
#, c-format
msgid "option file '%s': %s\n"
msgstr "file con opzioni predefinite '%s': %s\n"
-#: g10/g10.c:627
+#: g10/g10.c:629
#, c-format
msgid "reading options from '%s'\n"
msgstr "lettura delle opzioni da '%s'\n"
-#: g10/g10.c:776
+#: g10/g10.c:782
#, fuzzy, c-format
msgid "%s is not a valid character set\n"
msgstr "Carattere non valido nel commento\n"
-#: g10/g10.c:810 g10/g10.c:822
+#: g10/g10.c:817 g10/g10.c:829
msgid "selected cipher algorithm is invalid\n"
msgstr "l'algoritmo di cifratura selezionato non è valido\n"
-#: g10/g10.c:816 g10/g10.c:828
+#: g10/g10.c:823 g10/g10.c:835
msgid "selected digest algorithm is invalid\n"
msgstr "l'algoritmo di digest selezionato non è valido\n"
-#: g10/g10.c:831
+#: g10/g10.c:838
#, c-format
msgid "compress algorithm must be in range %d..%d\n"
msgstr "l'algoritmo di compressione deve essere tra %d e %d\n"
-#: g10/g10.c:833
+#: g10/g10.c:840
msgid "completes-needed must be greater than 0\n"
msgstr "completes-needed deve essere maggiore di 0\n"
-#: g10/g10.c:835
+#: g10/g10.c:842
msgid "marginals-needed must be greater than 1\n"
msgstr "marginals-needed deve essere maggiore di 1\n"
-#: g10/g10.c:837
+#: g10/g10.c:844
msgid "max-cert-depth must be in range 1 to 255\n"
msgstr ""
-#: g10/g10.c:840
+#: g10/g10.c:847
#, fuzzy
msgid "NOTE: simple S2K mode (0) is strongly discouraged\n"
msgstr "nota: il modo S2K semplice (0) è fortemente scoraggiato\n"
-#: g10/g10.c:844
+#: g10/g10.c:851
msgid "invalid S2K mode; must be 0, 1 or 3\n"
msgstr "modo S2K non valido; deve essere 0, 1 o 3\n"
-#: g10/g10.c:927
+#: g10/g10.c:934
#, c-format
msgid "failed to initialize the TrustDB: %s\n"
msgstr "inizializzazione del trustdb fallita: %s\n"
-#: g10/g10.c:933
+#: g10/g10.c:940
msgid "--store [filename]"
msgstr "--store [nomefile]"
-#: g10/g10.c:941
+#: g10/g10.c:948
msgid "--symmetric [filename]"
msgstr "--symmetric [nomefile]"
-#: g10/g10.c:949
+#: g10/g10.c:956
msgid "--encrypt [filename]"
msgstr "--encrypt [nomefile]"
-#: g10/g10.c:962
+#: g10/g10.c:969
msgid "--sign [filename]"
msgstr "--sign [nomefile]"
-#: g10/g10.c:975
+#: g10/g10.c:982
msgid "--sign --encrypt [filename]"
msgstr "--sign --encrypt [nomefile]"
-#: g10/g10.c:989
+#: g10/g10.c:996
msgid "--clearsign [filename]"
msgstr "--clearsign [nomefile]"
-#: g10/g10.c:1001
+#: g10/g10.c:1008
msgid "--decrypt [filename]"
msgstr "--decrypt [nomefile]"
-#: g10/g10.c:1010
+#: g10/g10.c:1017
#, fuzzy
msgid "--edit-key username [commands]"
msgstr "--edit-key nomeutente"
-#: g10/g10.c:1026
+#: g10/g10.c:1033
msgid "--delete-secret-key username"
msgstr "--delete-secret-key nomeutente"
-#: g10/g10.c:1029
+#: g10/g10.c:1036
msgid "--delete-key username"
msgstr "--delete-key nomeutente"
-#: g10/encode.c:216 g10/g10.c:1052 g10/sign.c:301
+#: g10/encode.c:216 g10/g10.c:1059 g10/sign.c:301
#, c-format
msgid "can't open %s: %s\n"
msgstr "impossibile aprire '%s': %s\n"
-#: g10/g10.c:1063
+#: g10/g10.c:1070
msgid "-k[v][v][v][c] [userid] [keyring]"
msgstr "-k[v][v][v][c] [userid] [portachiavi]"
-#: g10/g10.c:1120
+#: g10/g10.c:1127
#, c-format
msgid "dearmoring failed: %s\n"
msgstr "rimozione dell'armatura fallita: %s\n"
-#: g10/g10.c:1128
+#: g10/g10.c:1135
#, c-format
msgid "enarmoring failed: %s\n"
msgstr "creazione dell'armatura fallita: %s\n"
-#: g10/g10.c:1194
+#: g10/g10.c:1201
#, c-format
msgid "invalid hash algorithm '%s'\n"
msgstr "algoritmo di hash non valido '%s'\n"
-#: g10/g10.c:1273
+#: g10/g10.c:1280
msgid "[filename]"
msgstr "[nomefile]"
-#: g10/g10.c:1277
+#: g10/g10.c:1284
msgid "Go ahead and type your message ...\n"
msgstr ""
-#: g10/decrypt.c:59 g10/g10.c:1280 g10/verify.c:66
+#: g10/decrypt.c:59 g10/g10.c:1287 g10/verify.c:66
#, c-format
msgid "can't open '%s'\n"
msgstr "impossibile aprire '%s'\n"
#: g10/armor.c:344 g10/armor.c:391
msgid "armor header: "
msgstr "header dell'armatura: "
#: g10/armor.c:355
msgid "invalid clearsig header\n"
msgstr "header della firma in chiaro non valido\n"
#: g10/armor.c:382
msgid "invalid armor header: "
msgstr "header dell'armatura non valido: "
#: g10/armor.c:460
#, c-format
msgid "armor: %s\n"
msgstr "armatura: %s\n"
#: g10/armor.c:533
msgid "invalid dash escaped line: "
msgstr "riga protetta con il trattino non valida: "
#: g10/armor.c:602
msgid "invalid clear text header: "
msgstr "header del testo in chiaro non valido: "
#: g10/armor.c:845
#, c-format
msgid "invalid radix64 character %02x skipped\n"
msgstr "Carattere radix64 non valido %02x saltato\n"
#: g10/armor.c:878
msgid "premature eof (no CRC)\n"
msgstr "eof prematura (nessun CRC)\n"
#: g10/armor.c:897
msgid "premature eof (in CRC)\n"
msgstr "eof prematura (nel CRC)\n"
#: g10/armor.c:901
msgid "malformed CRC\n"
msgstr "CRC malformato\n"
#: g10/armor.c:905
#, c-format
msgid "CRC error; %06lx - %06lx\n"
msgstr "errore nel CRC; %06lx - %06lx\n"
#: g10/armor.c:924
msgid "premature eof (in Trailer)\n"
msgstr "eof prematura (nella coda)\n"
#: g10/armor.c:928
msgid "error in trailer line\n"
msgstr "errore nella riga della coda\n"
#: g10/armor.c:1182
msgid "no valid RFC1991 or OpenPGP data found.\n"
msgstr "Non sono stati trovati dati RFC1991 o OpenPGP validi.\n"
-#: g10/pkclist.c:121
+#: g10/pkclist.c:138
#, fuzzy, c-format
msgid ""
"No trust value assigned to %lu:\n"
"%4u%c/%08lX %s \""
msgstr ""
"Nessun valore di fiducia del proprietario definito per %lu:\n"
"%4u%c/%08lX %s \""
-#: g10/pkclist.c:131
+#: g10/pkclist.c:148
msgid ""
"Please decide how far you trust this user to correctly\n"
"verify other users' keys (by looking at passports,\n"
"checking fingerprints from different sources...)?\n"
"\n"
" 1 = Don't know\n"
" 2 = I do NOT trust\n"
" 3 = I trust marginally\n"
" 4 = I trust fully\n"
" s = please show me more information\n"
msgstr ""
"Per favore decidi quanto hai fiducia di questo utente perchè firmi\n"
"correttamente le chiavi di altri utenti (guardando il loro passaporto,\n"
"controllando le impronte digitali da diverse fonti ...)?\n"
"\n"
" 1 = Non lo so\n"
" 2 = NON mi fido\n"
" 3 = Mi fido marginalmente\n"
" 4 = Mi fido completamente\n"
" s = mostrami ulteriori informazioni\n"
-#: g10/pkclist.c:140
+#: g10/pkclist.c:157
msgid " m = back to the main menu\n"
msgstr " m = ritorna al menù principale\n"
+#: g10/pkclist.c:159
+msgid " q = quit\n"
+msgstr ""
+
# valid user replies (not including 1..4)
# [Marco, you can change 'm' and 's' to whatever letters you like]
#. a string with valid answers
-#: g10/pkclist.c:145
-msgid "sSmM"
-msgstr "sSmM"
+#: g10/pkclist.c:164
+#, fuzzy
+msgid "sSmMqQ"
+msgstr "sSmMqQ"
-#: g10/pkclist.c:149
+#: g10/pkclist.c:168
msgid "Your decision? "
msgstr "Cosa hai deciso? "
-#: g10/pkclist.c:169
+#: g10/pkclist.c:188
msgid "Certificates leading to an ultimately trusted key:\n"
msgstr ""
-#: g10/pkclist.c:197
+#: g10/pkclist.c:221
msgid ""
"Could not find a valid trust path to the key. Let's see whether we\n"
"can assign some missing owner trust values.\n"
"\n"
msgstr ""
"Impossibile trovare un percorso di fiducia valido fino alla chiave. Vediamo\n"
"se possiamo assegnare qualche valore di fiducia del proprietario mancante.\n"
"\n"
-#: g10/pkclist.c:219
+#: g10/pkclist.c:251
msgid ""
"No path leading to one of our keys found.\n"
"\n"
msgstr ""
-#: g10/pkclist.c:221
+#: g10/pkclist.c:253
msgid ""
"No certificates with undefined trust found.\n"
"\n"
msgstr ""
-#: g10/pkclist.c:223
+#: g10/pkclist.c:255
#, fuzzy
msgid ""
"No trust values changed.\n"
"\n"
msgstr ""
"Nessun valore di fiducia del proprietario modificato.\n"
"\n"
-#: g10/pkclist.c:238
+#: g10/pkclist.c:270
#, fuzzy, c-format
msgid "key %08lX: key has been revoked!\n"
msgstr "chiave %08lX: accettata come chiave segreta\n"
-#: g10/pkclist.c:244 g10/pkclist.c:335
+#: g10/pkclist.c:276 g10/pkclist.c:369
msgid "Use this key anyway? "
msgstr "Uso lo stesso questa chiave? "
-#: g10/pkclist.c:266
+#: g10/pkclist.c:298
#, fuzzy, c-format
msgid "%08lX: key has expired\n"
msgstr "Nota: questa chiave è scaduta!\n"
-#: g10/pkclist.c:272
+#: g10/pkclist.c:304
#, c-format
msgid "%08lX: no info to calculate a trust probability\n"
msgstr ""
-#: g10/pkclist.c:288
+#: g10/pkclist.c:322
#, fuzzy, c-format
msgid "%08lX: We do NOT trust this key\n"
msgstr "ATTENZIONE: NON ci fidiamo di questa chiave!\n"
-#: g10/pkclist.c:294
+#: g10/pkclist.c:328
#, c-format
msgid ""
"%08lX: It is not sure that this key really belongs to the owner\n"
"but it is accepted anyway\n"
msgstr ""
-#: g10/pkclist.c:300
+#: g10/pkclist.c:334
msgid "This key probably belongs to the owner\n"
msgstr ""
-#: g10/pkclist.c:305
+#: g10/pkclist.c:339
msgid "This key belongs to us\n"
msgstr ""
-#: g10/pkclist.c:330
+#: g10/pkclist.c:364
msgid ""
"It is NOT certain that the key belongs to its owner.\n"
"If you *really* know what you are doing, you may answer\n"
"the next question with yes\n"
"\n"
msgstr ""
"NON è sicuro che la chiave appartenga al suo proprietario.\n"
"Se *veramente* sai cosa stai facendo, puoi rispondere sì alla\n"
"prossima domanda.\n"
"\n"
-#: g10/pkclist.c:339
+#: g10/pkclist.c:373
msgid "WARNING: Using untrusted key!\n"
msgstr "ATTENZIONE: uso di una chiave non fidata!\n"
-#: g10/pkclist.c:375
+#: g10/pkclist.c:409
msgid "WARNING: This key has been revoked by its owner!\n"
msgstr "ATTENZIONE: questa chiave è stata revocata dal suo proprietario!\n"
-#: g10/pkclist.c:376
+#: g10/pkclist.c:410
msgid " This could mean that the signature is forgery.\n"
msgstr " Questo può significare che la firma è stata falsificata.\n"
-#: g10/pkclist.c:397
+#: g10/pkclist.c:431
msgid "Note: This key has expired!\n"
msgstr "Nota: questa chiave è scaduta!\n"
-#: g10/pkclist.c:404
+#: g10/pkclist.c:438
msgid "WARNING: This key is not certified with a trusted signature!\n"
msgstr "ATTENZIONE: questa chiave non è certificata con una firma fidata!\n"
-#: g10/pkclist.c:406
+#: g10/pkclist.c:440
msgid ""
" There is no indication that the signature belongs to the owner.\n"
msgstr ""
" Non ci sono indicazioni che la firma appartenga al proprietario.\n"
-#: g10/pkclist.c:421
+#: g10/pkclist.c:456
msgid "WARNING: We do NOT trust this key!\n"
msgstr "ATTENZIONE: NON ci fidiamo di questa chiave!\n"
-#: g10/pkclist.c:422
+#: g10/pkclist.c:457
msgid " The signature is probably a FORGERY.\n"
msgstr " La firma è probabilmente un FALSO.\n"
-#: g10/pkclist.c:429
+#: g10/pkclist.c:464
msgid ""
"WARNING: This key is not certified with sufficiently trusted signatures!\n"
msgstr ""
"ATTENZIONE: questa chiave non è certificata con firme abbastanza fidate!\n"
-#: g10/pkclist.c:432
+#: g10/pkclist.c:467
msgid " It is not certain that the signature belongs to the owner.\n"
msgstr " Non è sicuro che la firma appartenga al proprietario.\n"
-#: g10/pkclist.c:477
+#: g10/pkclist.c:512
msgid ""
"You did not specify a user ID. (you may use \"-r\")\n"
"\n"
msgstr ""
"Non hai specificato un user ID. (puoi usare \"-r\")\n"
"\n"
-#: g10/pkclist.c:482
+#: g10/pkclist.c:517
msgid "Enter the user ID: "
msgstr "Inserisci l'user ID: "
-#: g10/pkclist.c:493
+#: g10/pkclist.c:528
msgid "No such user ID.\n"
msgstr "User ID inesistente.\n"
-#: g10/pkclist.c:527 g10/pkclist.c:554
+#: g10/pkclist.c:562 g10/pkclist.c:589
#, c-format
msgid "%s: skipped: %s\n"
msgstr "%s: saltata: %s\n"
-#: g10/pkclist.c:535
+#: g10/pkclist.c:570
#, c-format
msgid "%s: error checking key: %s\n"
msgstr "%s: errore nel controllare la chiave: %s\n"
-#: g10/pkclist.c:561
+#: g10/pkclist.c:596
msgid "no valid addressees\n"
msgstr "nessun indirizzo valido\n"
#: g10/keygen.c:124
msgid "writing self signature\n"
msgstr "scrittura della autofirma\n"
#: g10/keygen.c:162
msgid "writing key binding signature\n"
msgstr "scrittura della autofirma\n"
#: g10/keygen.c:388
msgid "Please select what kind of key you want:\n"
msgstr "Per favore scegli che tipo di chiave vuoi:\n"
#: g10/keygen.c:390
#, c-format
msgid " (%d) DSA and ElGamal (default)\n"
msgstr " (%d) DSA e ElGamal (default)\n"
#: g10/keygen.c:391
#, c-format
msgid " (%d) DSA (sign only)\n"
msgstr " (%d) DSA (firma solo)\n"
#: g10/keygen.c:393
#, c-format
msgid " (%d) ElGamal (encrypt only)\n"
msgstr " (%d) ElGamal (crittografa solo)\n"
#: g10/keygen.c:394
#, c-format
msgid " (%d) ElGamal (sign and encrypt)\n"
msgstr " (%d) ElGamal (firma e crittografa)\n"
#: g10/keygen.c:396
#, c-format
msgid " (%d) ElGamal in a v3 packet\n"
msgstr " (%d) ElGamal in un pacchetto v3\n"
#: g10/keygen.c:401
msgid "Your selection? "
msgstr "Cosa scegli? "
#: g10/keygen.c:411
#, fuzzy
msgid "Do you really want to create a sign and encrypt key? "
msgstr "Vuoi davvero cancellare le chiavi selezionate? "
#: g10/keygen.c:432
msgid "Invalid selection.\n"
msgstr "Scelta non valida.\n"
#: g10/keygen.c:444
#, c-format
msgid ""
"About to generate a new %s keypair.\n"
" minimum keysize is 768 bits\n"
" default keysize is 1024 bits\n"
" highest suggested keysize is 2048 bits\n"
msgstr ""
"Sto per generare una nuova coppia di chiavi %s.\n"
" la dimensione minima è 768 bit\n"
" la dimensione predefinita è 1024 bit\n"
" la dimensione massima consigliata è 2048 bit\n"
#: g10/keygen.c:451
msgid "What keysize do you want? (1024) "
msgstr "Di che dimensioni vuoi la chiave? (1024) "
#: g10/keygen.c:456
msgid "DSA only allows keysizes from 512 to 1024\n"
msgstr "DSA permette solo chiavi di dimensioni da 512 a 1024\n"
#: g10/keygen.c:458
msgid "keysize too small; 768 is smallest value allowed.\n"
msgstr "la chiave è troppo corta; 768 è il minimo valore permesso.\n"
#: g10/keygen.c:461
msgid ""
"Keysizes larger than 2048 are not suggested because\n"
"computations take REALLY long!\n"
msgstr ""
"Chiavi più lunghe di 2048 non sono consigliate perchè i calcoli sono \n"
"VERAMENTE lunghi!\n"
#: g10/keygen.c:464
msgid "Are you sure that you want this keysize? "
msgstr "Sei sicuro di volere una chiave di queste dimensioni? "
#: g10/keygen.c:465
msgid ""
"Okay, but keep in mind that your monitor and keyboard radiation is also very "
"vulnerable to attacks!\n"
msgstr ""
"Va bene, ma ricordati che anche le radiazioni emesse dal tuo monitor e dalla "
"tua tastiera sono molto vulnerabili ad attacchi!\n"
#: g10/keygen.c:473
msgid "Do you really need such a large keysize? "
msgstr "Ti serve davvero una chiave così lunga? "
#: g10/keygen.c:479
#, c-format
msgid "Requested keysize is %u bits\n"
msgstr "Le dimensioni della chiave richieste sono %u bit\n"
#: g10/keygen.c:482 g10/keygen.c:486
#, c-format
msgid "rounded up to %u bits\n"
msgstr "arrotondate a %u bit\n"
#: g10/keygen.c:499
msgid ""
"Please specify how long the key should be valid.\n"
" 0 = key does not expire\n"
" <n> = key expires in n days\n"
" <n>w = key expires in n weeks\n"
" <n>m = key expires in n months\n"
" <n>y = key expires in n years\n"
msgstr ""
"Per favore specifica per quanto la chiave sarà valida.\n"
" 0 = la chiave non scadrà\n"
" <n>w = la chiave scadrà dopo n giorni\n"
" <n>m = la chiave scadrà dopo n mesi\n"
" <n>y = la chiave scadrà dopo n anni\n"
#: g10/keygen.c:514
msgid "Key is valid for? (0) "
msgstr "Chiave valida per? (0) "
#: g10/keygen.c:525
msgid "invalid value\n"
msgstr "valore non valido\n"
#: g10/keygen.c:530
msgid "Key does not expire at all\n"
msgstr "La chiave non scade\n"
#. print the date when the key expires
#: g10/keygen.c:536
#, c-format
msgid "Key expires at %s\n"
msgstr "La chiave scadrà il %s\n"
#: g10/keygen.c:542
msgid "Is this correct (y/n)? "
msgstr "È giusto (s/n)? "
#: g10/keygen.c:584
msgid ""
"\n"
"You need a User-ID to identify your key; the software constructs the user "
"id\n"
"from Real Name, Comment and Email Address in this form:\n"
" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n"
"\n"
msgstr ""
"\n"
"Ti serve un User ID per identificare la tua chiave; il software costruisce "
"l'user id a partire da Nome e Cognome, Commento e Indirizzo di Email "
"indicati in questa forma:\n"
" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n"
"\n"
#: g10/keygen.c:595
msgid "Real name: "
msgstr "Nome e Cognome: "
#: g10/keygen.c:599
msgid "Invalid character in name\n"
msgstr "Carattere non valido nel nome\n"
#: g10/keygen.c:601
msgid "Name may not start with a digit\n"
msgstr "Il nome non può iniziare con una cifra\n"
#: g10/keygen.c:603
msgid "Name must be at least 5 characters long\n"
msgstr "Il nome deve essere lungo almeno 5 caratteri\n"
#: g10/keygen.c:611
msgid "Email address: "
msgstr "Indirizzo di Email: "
#: g10/keygen.c:623
msgid "Not a valid email address\n"
msgstr "L'indirizzo di email non è valido\n"
#: g10/keygen.c:631
msgid "Comment: "
msgstr "Commento: "
#: g10/keygen.c:637
msgid "Invalid character in comment\n"
msgstr "Carattere non valido nel commento\n"
#: g10/keygen.c:657
#, c-format
msgid ""
"You selected this USER-ID:\n"
" \"%s\"\n"
"\n"
msgstr ""
"Hai selezionato questo User Id:\n"
" \"%s\"\n"
"\n"
#: g10/keygen.c:660
msgid "NnCcEeOoQq"
msgstr "NnCcEeOoQq"
#: g10/keygen.c:670
msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? "
msgstr "Modifica (N)ome, (C)ommento, (E)mail oppure (O)kay/(Q)uit? "
#: g10/keygen.c:722
msgid ""
"You need a Passphrase to protect your secret key.\n"
"\n"
msgstr ""
"Ti serve una passphrase per proteggere la tua chiave segreta.\n"
"\n"
#: g10/keyedit.c:389 g10/keygen.c:730
msgid "passphrase not correctly repeated; try again.\n"
msgstr "passphrase non ripetuta correttamente; riprova.\n"
#: g10/keygen.c:736
msgid ""
"You don't want a passphrase - this is probably a *bad* idea!\n"
"I will do it anyway. You can change your passphrase at any time,\n"
"using this program with the option \"--edit-key\".\n"
"\n"
msgstr ""
"Non hai specificato una passphrase - questa è probabilmente una *cattiva*\n"
"idea! Lo farò io comunque. Puoi cambiarla in ogni momento, usando questo\n"
"programma con l'opzione \"--edit-key\".\n"
"\n"
#: g10/keygen.c:757
msgid ""
"We need to generate a lot of random bytes. It is a good idea to perform\n"
"some other action (work in another window, move the mouse, utilize the\n"
"network and the disks) during the prime generation; this gives the random\n"
"number generator a better chance to gain enough entropy.\n"
msgstr ""
"Dobbiamo generare un mucchio di byte casuali. È una buona idea eseguire\n"
"qualche altra azione (lavorare in un'altra finestra, muovere il mouse, "
"usare\n"
"la rete e i dischi) durante la generazione dei numeri primi; questo dà al\n"
"generatore di numeri casuali la possibilità di raccogliere abbastanza\n"
"entropia.\n"
#: g10/keygen.c:827
msgid "Key generation can only be used in interactive mode\n"
msgstr "Una chiave può essere generata solo in modo interattivo\n"
#: g10/keygen.c:835
msgid "DSA keypair will have 1024 bits.\n"
msgstr "La coppia DSA avrà 1024 bit.\n"
#: g10/keygen.c:841
msgid "Key generation cancelled.\n"
msgstr "Generazione della chiave annullata.\n"
#: g10/keygen.c:851
#, c-format
msgid "writing public certificate to '%s'\n"
msgstr "scrittura del certificato pubblico in '%s'\n"
#: g10/keygen.c:852
#, c-format
msgid "writing secret certificate to '%s'\n"
msgstr "scrittura del certificato privato in '%s'\n"
#: g10/keygen.c:929
msgid "public and secret key created and signed.\n"
msgstr "chiavi pubbliche e segrete create e firmate.\n"
#: g10/keygen.c:931
msgid ""
"Note that this key cannot be used for encryption. You may want to use\n"
"the command \"--add-key\" to generate a secondary key for this purpose.\n"
msgstr ""
"Nota che questa chiave non può essere usata per la crittografia. Forse\n"
"vorrai usare il comando \"--add-key\" per generare una chiave secondaria\n"
"per questo scopo.\n"
#: g10/keygen.c:945 g10/keygen.c:1030
#, c-format
msgid "Key generation failed: %s\n"
msgstr "Generazione della chiave fallita: %s\n"
#: g10/keygen.c:1008
msgid "Really create? "
msgstr "Crea davvero? "
#: g10/encode.c:88 g10/openfile.c:81 g10/openfile.c:158 g10/tdbio.c:445
#: g10/tdbio.c:504
#, c-format
msgid "%s: can't open: %s\n"
msgstr "%s: impossibile aprire: %s\n"
#: g10/encode.c:107
#, c-format
msgid "error creating passphrase: %s\n"
msgstr "errore nella creazione della passhprase: %s\n"
#: g10/encode.c:155 g10/encode.c:269
#, fuzzy, c-format
msgid "%s: WARNING: empty file\n"
msgstr "%s: attenzione: file vuoto\n"
#: g10/encode.c:222
#, c-format
msgid "reading from '%s'\n"
msgstr "lettura da '%s'\n"
#: g10/encode.c:397
#, fuzzy, c-format
msgid "%s/%s encrypted for: %s\n"
msgstr "%s crittografato per: %s\n"
#: g10/export.c:114
#, fuzzy, c-format
msgid "%s: user not found: %s\n"
msgstr "%s: utente non trovato\n"
#: g10/export.c:123
#, c-format
msgid "certificate read problem: %s\n"
msgstr ""
#: g10/export.c:132
#, fuzzy, c-format
msgid "key %08lX: not a rfc2440 key - skipped\n"
msgstr "chiave %08lX: chiave segreta senza chiave pubblica - saltata\n"
#: g10/export.c:174
#, fuzzy
msgid "WARNING: nothing exported\n"
msgstr "ATTENZIONE: uso di una chiave non fidata!\n"
#: g10/getkey.c:164
msgid "too many entries in pk cache - disabled\n"
msgstr ""
#: g10/getkey.c:263
msgid "too many entries in unk cache - disabled\n"
msgstr ""
#: g10/getkey.c:989
#, c-format
msgid "using secondary key %08lX instead of primary key %08lX\n"
msgstr "uso la chiave secondaria %08lX invece della chiave primaria %08lX\n"
-#: g10/import.c:129 g10/trustdb.c:1166
+#: g10/import.c:129 g10/trustdb.c:1180
#, c-format
msgid "can't open file: %s\n"
msgstr "impossibile aprire il file: %s\n"
#: g10/import.c:145
#, c-format
msgid "skipping block of type %d\n"
msgstr "salto un blocco di tipo %d\n"
-#: g10/import.c:152 g10/trustdb.c:1425 g10/trustdb.c:1494
+#: g10/import.c:152 g10/trustdb.c:1474 g10/trustdb.c:1543
#, c-format
msgid "%lu keys so far processed\n"
msgstr "Per ora sono state esaminate %lu chiavi\n"
-#: g10/import.c:157 g10/trustdb.c:1242
+#: g10/import.c:157 g10/trustdb.c:1256
#, c-format
msgid "read error: %s\n"
msgstr "errore di lettura: %s\n"
#: g10/import.c:159
#, c-format
msgid "Total number processed: %lu\n"
msgstr "Numero totale esaminato: %lu\n"
#: g10/import.c:161
#, c-format
msgid " w/o user IDs: %lu\n"
msgstr "senza user ID: %lu\n"
#: g10/import.c:163
#, c-format
msgid " imported: %lu"
msgstr "importate: %lu"
#: g10/import.c:169
#, c-format
msgid " unchanged: %lu\n"
msgstr "non modificate: %lu\n"
#: g10/import.c:171
#, c-format
msgid " new user IDs: %lu\n"
msgstr "nuovi user ID: %lu\n"
#: g10/import.c:173
#, c-format
msgid " new subkeys: %lu\n"
msgstr "nuove subchiavi: %lu\n"
#: g10/import.c:175
#, c-format
msgid " new signatures: %lu\n"
msgstr "nuove firme: %lu\n"
#: g10/import.c:177
#, c-format
msgid " new key revocations: %lu\n"
msgstr "nuove revoche di chiavi: %lu\n"
#: g10/import.c:179
#, c-format
msgid " secret keys read: %lu\n"
msgstr "chiavi segrete lette: %lu\n"
#: g10/import.c:181
#, c-format
msgid " secret keys imported: %lu\n"
msgstr "chiavi segrete importate %lu\n"
#: g10/import.c:183
#, c-format
msgid " secret keys unchanged: %lu\n"
msgstr "chiavi segrete non cambiate %lu\n"
#: g10/import.c:325 g10/import.c:517
#, c-format
msgid "key %08lX: no user id\n"
msgstr "chiave %08lX: nessun user id\n"
#: g10/import.c:336
#, c-format
msgid "key %08lX: no valid user ids\n"
msgstr "chiave %08lX: nessun user id valido\n"
#: g10/import.c:338
msgid "this may be caused by a missing self-signature\n"
msgstr "questo può essere causato da una autofirma mancante\n"
#: g10/import.c:349 g10/import.c:585
#, c-format
msgid "key %08lX: public key not found: %s\n"
msgstr "chiave %08lX: chiave pubblica non trovata: %s\n"
#: g10/import.c:355
msgid "no default public keyring\n"
msgstr "nessun portachiavi pubblico predefinito\n"
-#: g10/import.c:359 g10/openfile.c:105 g10/sign.c:205 g10/sign.c:569
+#: g10/import.c:359 g10/openfile.c:105 g10/sign.c:205 g10/sign.c:592
#, c-format
msgid "writing to '%s'\n"
msgstr "scrittura in '%s'\n"
#: g10/import.c:363 g10/import.c:423 g10/import.c:639
#, c-format
msgid "can't lock public keyring: %s\n"
msgstr "impossibile bloccare il portachiavi pubblico: %s\n"
#: g10/import.c:366
#, c-format
msgid "can't write to keyring: %s\n"
msgstr "impossibile scrivere sul portachiavi pubblico: %s\n"
#: g10/import.c:370
#, c-format
msgid "key %08lX: public key imported\n"
msgstr "chiave %08lX: chiave pubblica importata\n"
#: g10/import.c:383
#, c-format
msgid "key %08lX: doesn't match our copy\n"
msgstr "chiave %08lX: non corrisponde alla nostra copia\n"
#: g10/import.c:396 g10/import.c:594
#, c-format
msgid "key %08lX: can't locate original keyblock: %s\n"
msgstr "chiave %08lX: impossibile individuare il keyblock originale: %s\n"
#: g10/import.c:403 g10/import.c:601
#, c-format
msgid "key %08lX: can't read original keyblock: %s\n"
msgstr "chiave %08lX: impossibile leggere il keyblock originale: %s\n"
#: g10/import.c:420 g10/import.c:532 g10/import.c:636
msgid "writing keyblock\n"
msgstr "scrittura del keyblock\n"
#: g10/import.c:426 g10/import.c:642
#, c-format
msgid "can't write keyblock: %s\n"
msgstr "impossibile aprire il keyblock: %s\n"
#: g10/import.c:431
#, c-format
msgid "key %08lX: 1 new user-id\n"
msgstr "chiave %08lX: un nuovo user id\n"
#: g10/import.c:434
#, c-format
msgid "key %08lX: %d new user-ids\n"
msgstr "chiave %08lX: %d nuovi user id\n"
#: g10/import.c:437
#, c-format
msgid "key %08lX: 1 new signature\n"
msgstr "chiave %08lX: una nuova firma\n"
#: g10/import.c:440
#, c-format
msgid "key %08lX: %d new signatures\n"
msgstr "chiave %08lX: %d nuove firme\n"
#: g10/import.c:443
#, c-format
msgid "key %08lX: 1 new subkey\n"
msgstr "chiave %08lX: una nuova subchiave\n"
#: g10/import.c:446
#, c-format
msgid "key %08lX: %d new subkeys\n"
msgstr "chiave %08lX: %d nuove subchiavi\n"
#: g10/import.c:456
#, c-format
msgid "key %08lX: not changed\n"
msgstr "chiave %08lX: non cambiata\n"
#: g10/import.c:535
#, c-format
msgid "can't lock secret keyring: %s\n"
msgstr "impossibile bloccare il portachiavi segreto: %s\n"
#: g10/import.c:538
#, c-format
msgid "can't write keyring: %s\n"
msgstr "impossibile scrivere il portachiavi: %s\n"
#. we are ready
#: g10/import.c:541
#, c-format
msgid "key %08lX: secret key imported\n"
msgstr "chiave %08lX: chiave segreta importata\n"
#. we can't merge secret keys
#: g10/import.c:545
#, c-format
msgid "key %08lX: already in secret keyring\n"
msgstr "chiave %08lX: già nel portachiavi segreto\n"
#: g10/import.c:550
#, c-format
msgid "key %08lX: secret key not found: %s\n"
msgstr "chiave %08lX: chiave segreta non trovata: %s\n"
#: g10/import.c:579
#, c-format
msgid "key %08lX: no public key - can't apply revocation certificate\n"
msgstr ""
"chiave %08lX: manca la chiave pubblica - impossibile applicare il\n"
"certificato di revoca\n"
#: g10/import.c:612
#, c-format
msgid "key %08lX: invalid revocation certificate: %s - rejected\n"
msgstr "chiave %08lX: certificato di revoca non valido: %s - rifiutato\n"
#: g10/import.c:646
#, c-format
msgid "key %08lX: revocation certificate imported\n"
msgstr "chiave %08lX: certificato di revoca importato\n"
#: g10/import.c:677
#, c-format
msgid "key %08lX: no user-id for signature\n"
msgstr "chiave %08lX: nessun user id per la firma\n"
#: g10/import.c:684
#, c-format
msgid "key %08lX: unsupported public key algorithm\n"
msgstr "chiave %08lX: algoritmo a chiave pubblica non gestito\n"
#: g10/import.c:685
#, c-format
msgid "key %08lX: invalid self-signature\n"
msgstr "chiave %08lX: autofirma non valida\n"
#: g10/import.c:714
#, c-format
msgid "key %08lX: skipped userid '"
msgstr "chiave %08lX: saltato l'user id '"
#: g10/import.c:737
#, c-format
msgid "key %08lX: revocation certificate at wrong place - skipped\n"
msgstr "chiave %08lX: certificato di revoca nel posto sbagliato - saltato\n"
#: g10/import.c:745
#, c-format
msgid "key %08lX: invalid revocation certificate: %s - skipped\n"
msgstr "chiave %08lX: certificato di revoca non valido: %s - saltato\n"
#: g10/import.c:804
#, c-format
msgid "key %08lX: revocation certificate added\n"
msgstr "chiave %08lX: certificato di revoca aggiunto\n"
#: g10/import.c:918 g10/import.c:973
#, c-format
msgid "key %08lX: our copy has no self-signature\n"
msgstr "chiave %08lX: la nostra copia non ha autofirma\n"
#: g10/keyedit.c:81
#, c-format
msgid "%s: user not found\n"
msgstr "%s: utente non trovato\n"
#: g10/keyedit.c:164
msgid "[self-signature]"
msgstr "[autofirma]"
#: g10/keyedit.c:182
msgid "1 bad signature\n"
msgstr "una firma non corretta\n"
#: g10/keyedit.c:184
#, c-format
msgid "%d bad signatures\n"
msgstr "%d firme non corrette\n"
#: g10/keyedit.c:186
msgid "1 signature not checked due to a missing key\n"
msgstr "1 firma non controllata per mancanza della chiave\n"
#: g10/keyedit.c:188
#, c-format
msgid "%d signatures not checked due to missing keys\n"
msgstr "%d firme non controllate per mancanza delle chiavi\n"
#: g10/keyedit.c:190
msgid "1 signature not checked due to an error\n"
msgstr "1 firma non controllata a causa di un errore\n"
#: g10/keyedit.c:192
#, c-format
msgid "%d signatures not checked due to errors\n"
msgstr "%d firme non controllate a causa di errori\n"
#: g10/keyedit.c:194
msgid "1 user id without valid self-signature detected\n"
msgstr "Trovato 1 user id senza autofirma valida\n"
#: g10/keyedit.c:196
#, c-format
msgid "%d user ids without valid self-signatures detected\n"
msgstr "Trovati %d user id senza autofirme valide\n"
#: g10/keyedit.c:258
#, c-format
msgid "Already signed by key %08lX\n"
msgstr "Già firmato dalla chiave %08lX\n"
#: g10/keyedit.c:266
#, c-format
msgid "Nothing to sign with key %08lX\n"
msgstr "Niente da firmare con la chiave %08lX\n"
#: g10/keyedit.c:275
msgid ""
"Are you really sure that you want to sign this key\n"
"with your key: \""
msgstr ""
"Sei davvero sicuro di volere firmare questa chiave\n"
"con la tua chiave: \""
#: g10/keyedit.c:282
msgid "Really sign? "
msgstr "Firmo davvero? "
#: g10/keyedit.c:303 g10/sign.c:65
#, c-format
msgid "signing failed: %s\n"
msgstr "firma fallita: %s\n"
#: g10/keyedit.c:356
msgid "This key is not protected.\n"
msgstr "Questa chiave non è protetta.\n"
#: g10/keyedit.c:359
msgid "Key is protected.\n"
msgstr "La chiave è protetta.\n"
#: g10/keyedit.c:376
#, c-format
msgid "Can't edit this key: %s\n"
msgstr "Impossibile modificare questa chiave: %s\n"
#: g10/keyedit.c:381
msgid ""
"Enter the new passphrase for this secret key.\n"
"\n"
msgstr ""
"Inserisci la nuova passphrase per questa chiave segreta.\n"
"\n"
#: g10/keyedit.c:393
msgid ""
"You don't want a passphrase - this is probably a *bad* idea!\n"
"\n"
msgstr ""
"Non vuoi una passphrase - questa è probabilmente una *cattiva* idea!\n"
"\n"
#: g10/keyedit.c:396
msgid "Do you really want to do this? "
msgstr "Vuoi veramente farlo?"
#: g10/keyedit.c:455
msgid "moving a key signature to the correct place\n"
msgstr ""
#: g10/keyedit.c:490
msgid "quit"
msgstr "quit"
#: g10/keyedit.c:490
msgid "quit this menu"
msgstr "abbandona questo menù"
#: g10/keyedit.c:491
msgid "q"
msgstr "q"
#: g10/keyedit.c:492
msgid "save"
msgstr "save"
#: g10/keyedit.c:492
msgid "save and quit"
msgstr "salva ed esci"
#: g10/keyedit.c:493
msgid "help"
msgstr "help"
#: g10/keyedit.c:493
msgid "show this help"
msgstr "mostra questo aiuto"
#: g10/keyedit.c:495
msgid "fpr"
msgstr "fpr"
#: g10/keyedit.c:495
msgid "show fingerprint"
msgstr "mostra le impronte digitali"
#: g10/keyedit.c:496
msgid "list"
msgstr "list"
#: g10/keyedit.c:496
msgid "list key and user ids"
msgstr "elenca le chiavi e gli user id"
#: g10/keyedit.c:497
msgid "l"
msgstr "l"
#: g10/keyedit.c:498
msgid "uid"
msgstr "uid"
#: g10/keyedit.c:498
msgid "select user id N"
msgstr "scegli l'user id N"
#: g10/keyedit.c:499
msgid "key"
msgstr "key"
#: g10/keyedit.c:499
msgid "select secondary key N"
msgstr "scegli la chiave secondaria N"
#: g10/keyedit.c:500
msgid "check"
msgstr "check"
#: g10/keyedit.c:500
msgid "list signatures"
msgstr "elenca le firme"
#: g10/keyedit.c:501
msgid "c"
msgstr "c"
#: g10/keyedit.c:502
msgid "sign"
msgstr "sign"
#: g10/keyedit.c:502
msgid "sign the key"
msgstr "firma la chiave"
#: g10/keyedit.c:503
msgid "s"
msgstr "s"
#: g10/keyedit.c:504
msgid "debug"
msgstr "debug"
#: g10/keyedit.c:505
msgid "adduid"
msgstr "adduid"
#: g10/keyedit.c:505
msgid "add a user id"
msgstr "aggiungi un user id"
#: g10/keyedit.c:506
msgid "deluid"
msgstr "deluid"
#: g10/keyedit.c:506
msgid "delete user id"
msgstr "cancella un user id"
#: g10/keyedit.c:507
msgid "addkey"
msgstr "addkey"
#: g10/keyedit.c:507
msgid "add a secondary key"
msgstr "aggiungi una chiave secondaria"
#: g10/keyedit.c:508
msgid "delkey"
msgstr "delkey"
#: g10/keyedit.c:508
msgid "delete a secondary key"
msgstr "cancella una chiave secondaria"
#: g10/keyedit.c:509
msgid "expire"
msgstr "expire"
#: g10/keyedit.c:509
msgid "change the expire date"
msgstr "cambia la data di scadenza"
#: g10/keyedit.c:510
msgid "toggle"
msgstr "toggle"
#: g10/keyedit.c:510
msgid "toggle between secret and public key listing"
msgstr "cambia tra visualizzare la chiave segreta e la chiave pubblica"
#: g10/keyedit.c:512
msgid "t"
msgstr "t"
#: g10/keyedit.c:513
msgid "pref"
msgstr "pref"
#: g10/keyedit.c:513
msgid "list preferences"
msgstr "elenca le impostazioni"
#: g10/keyedit.c:514
msgid "passwd"
msgstr "passwd"
#: g10/keyedit.c:514
msgid "change the passphrase"
msgstr "cambia la passphrase"
#: g10/keyedit.c:515
msgid "trust"
msgstr "trust"
#: g10/keyedit.c:515
msgid "change the ownertrust"
msgstr "cambia il valore di fiducia"
#: g10/keyedit.c:534
msgid "can't do that in batchmode\n"
msgstr "impossibile fare questo in batch mode\n"
#. check that they match
#. FIXME: check that they both match
#: g10/keyedit.c:561
msgid "Secret key is available.\n"
msgstr "È disponibile una chiave segreta.\n"
#: g10/keyedit.c:590
msgid "Command> "
msgstr "Comando> "
#: g10/keyedit.c:617
msgid "Need the secret key to do this.\n"
msgstr "Per fare questo serve la chiave segreta.\n"
#: g10/keyedit.c:639
msgid "Save changes? "
msgstr "Salvo i cambiamenti? "
#: g10/keyedit.c:642
msgid "Quit without saving? "
msgstr "Esco senza salvare? "
#: g10/keyedit.c:652
#, c-format
msgid "update failed: %s\n"
msgstr "aggiornamento fallito: %s\n"
#: g10/keyedit.c:659
#, c-format
msgid "update secret failed: %s\n"
msgstr "aggiornamento della chiave segreta fallito: %s\n"
#: g10/keyedit.c:666
msgid "Key not changed so no update needed.\n"
msgstr "La chiave non è cambiata quindi non sono necessari aggiornamenti.\n"
#: g10/keyedit.c:669 g10/keyedit.c:727
#, c-format
msgid "update of trust db failed: %s\n"
msgstr "aggiornamento del trustdb fallito: %s\n"
#: g10/keyedit.c:701
msgid "Really sign all user ids? "
msgstr "Firmo davvero tutti gli user id? "
#: g10/keyedit.c:702
msgid "Hint: Select the user ids to sign\n"
msgstr "Suggerimento: seleziona gli user id da firmare\n"
#: g10/keyedit.c:738
msgid "You must select at least one user id.\n"
msgstr "Devi selezionare almeno un user id.\n"
#: g10/keyedit.c:740
msgid "You can't delete the last user id!\n"
msgstr "Non puoi cancellare l'ultimo user id!\n"
#: g10/keyedit.c:743
msgid "Really remove all selected user ids? "
msgstr "Tolgo davvero tutti gli user id selezionati? "
#: g10/keyedit.c:744
msgid "Really remove this user id? "
msgstr "Tolgo davvero questo user id? "
#: g10/keyedit.c:767
msgid "You must select at least one key.\n"
msgstr "Devi selezionare almeno una chiave.\n"
#: g10/keyedit.c:771
msgid "Do you really want to delete the selected keys? "
msgstr "Vuoi davvero cancellare le chiavi selezionate? "
#: g10/keyedit.c:772
msgid "Do you really want to delete this key? "
msgstr "Vuoi davvero cancellare questa chiave? "
#: g10/keyedit.c:819
msgid "Invalid command (try \"help\")\n"
msgstr "Comando non valido (prova \"help\")\n"
#: g10/keyedit.c:1197
msgid "Please remove selections from the secret keys.\n"
msgstr "Togli le selezioni dalle chiavi segrete.\n"
#: g10/keyedit.c:1203
msgid "Please select at most one secondary key.\n"
msgstr "Seleziona al massimo una chiave secondaria.\n"
#: g10/keyedit.c:1207
msgid "Changing exiration time for a secondary key.\n"
msgstr "Modifico il tempo di scadenza per una chiave secondaria.\n"
#: g10/keyedit.c:1209
msgid "Changing exiration time for the primary key.\n"
msgstr "Modifico il tempo di scadenza per la chiave primaria.\n"
#: g10/keyedit.c:1250
msgid "You can't change the expiration date of a v3 key\n"
msgstr ""
#: g10/keyedit.c:1266
msgid "No corresponding signature in secret ring\n"
msgstr "Manca la firma corrispondente nel portachiavi segreto\n"
#: g10/keyedit.c:1326
#, c-format
msgid "No user id with index %d\n"
msgstr "Nessun user id con l'indice %d\n"
#: g10/keyedit.c:1371
#, c-format
msgid "No secondary key with index %d\n"
msgstr "Nessuna chiave secondaria con l'indice %d\n"
#: g10/mainproc.c:198
#, fuzzy
msgid "public key encrypted data: Good DEK\n"
msgstr "Decifratura della chiave pubblica fallita: %s\n"
#: g10/mainproc.c:201
#, c-format
msgid "public key decryption failed: %s\n"
msgstr "Decifratura della chiave pubblica fallita: %s\n"
#: g10/mainproc.c:228
#, fuzzy
msgid "decryption okay\n"
msgstr "decifratura fallita: %s\n"
#: g10/mainproc.c:231
#, c-format
msgid "decryption failed: %s\n"
msgstr "decifratura fallita: %s\n"
#: g10/mainproc.c:248
#, fuzzy
msgid "NOTE: sender requested \"for-your-eyes-only\"\n"
msgstr "nota: il mittente ha richiesto \"solo-per-i-tuoi-occhi\"\n"
#: g10/mainproc.c:250
#, c-format
msgid "original file name='%.*s'\n"
msgstr ""
#: g10/mainproc.c:833
msgid "signature verification suppressed\n"
msgstr ""
#: g10/mainproc.c:839
#, c-format
msgid "Signature made %.*s using %s key ID %08lX\n"
msgstr "Firma fatta %.*s usando %s key ID %08lX\n"
#: g10/mainproc.c:847
msgid "BAD signature from \""
msgstr "Firma NON corretta da \""
#: g10/mainproc.c:848
msgid "Good signature from \""
msgstr "Buona firma da \""
#: g10/mainproc.c:861
#, c-format
msgid "Can't check signature: %s\n"
msgstr "Impossibile controllare la firma: %s\n"
#: g10/mainproc.c:934
msgid "old style (PGP 2.x) signature\n"
msgstr ""
#: g10/mainproc.c:939
msgid "invalid root packet detected in proc_tree()\n"
msgstr ""
#: g10/misc.c:88
#, fuzzy, c-format
msgid "can't disable core dumps: %s\n"
msgstr "impossibile aprire '%s': %s\n"
#: g10/misc.c:90
msgid "WARNING: Program may create a core file!\n"
msgstr ""
#: g10/misc.c:198
msgid "Experimental algorithms should not be used!\n"
msgstr ""
#: g10/misc.c:212
msgid ""
"RSA keys are deprecated; please consider creating a new key and use this key "
"in the future\n"
msgstr ""
"L'uso di chiavi RSA è deprecato; per favore in futuro considera di creare e\n"
"usare una nuova chiave.\n"
#: g10/misc.c:233
msgid "This cipher algorithm is depreciated; please use a more standard one!\n"
msgstr ""
#: g10/parse-packet.c:109
#, fuzzy, c-format
msgid "can't handle public key algorithm %d\n"
msgstr "impossibile bloccare il portachiavi pubblico: %s\n"
+#: g10/parse-packet.c:801
+#, c-format
+msgid "subpacket of type %d has critical bit set\n"
+msgstr ""
+
#: g10/passphrase.c:141
msgid ""
"\n"
"You need a passphrase to unlock the secret key for\n"
"user: \""
msgstr ""
"\n"
"Ti serve una passphrase per sbloccare la chiave segreta\n"
"dell'utente: \""
#: g10/passphrase.c:150
#, c-format
msgid "(%u-bit %s key, ID %08lX, created %s)\n"
msgstr "(chiave %2$s di %1$u-bit, ID %3$08lX, creata il %4$s)\n"
#: g10/passphrase.c:174
#, fuzzy
msgid "Enter passphrase: "
msgstr "Inserisci la passphrase: "
#: g10/passphrase.c:178
#, fuzzy
msgid "Repeat passphrase: "
msgstr "Ripeti la passphrase: "
-#: g10/plaintext.c:102
+#: g10/plaintext.c:103
msgid "data not saved; use option \"--output\" to save it\n"
msgstr ""
"i dati non sono stati salvati; usa l'opzione \"--output\" per salvarli\n"
-#: g10/plaintext.c:215
+#: g10/plaintext.c:216
msgid "Please enter name of data file: "
msgstr "Inserisci il nome del file di dati: "
-#: g10/plaintext.c:236
+#: g10/plaintext.c:237
msgid "reading stdin ...\n"
msgstr ""
-#: g10/plaintext.c:299
+#: g10/plaintext.c:300
#, c-format
msgid "can't open signed data '%s'\n"
msgstr "impossibile aprire i dati firmati '%s'\n"
#: g10/pubkey-enc.c:78
#, c-format
msgid "anonymous receiver; trying secret key %08lX ...\n"
msgstr "ricevente anonimo; provo la chiave segreta %08lX ...\n"
#: g10/pubkey-enc.c:84
msgid "okay, we are the anonymous receiver.\n"
msgstr "Bene, siamo il ricevente anonimo.\n"
#: g10/pubkey-enc.c:136
#, fuzzy
msgid "old encoding of the DEK is not supported\n"
msgstr "l'algoritmo di protezione %d non è gestito\n"
#: g10/pubkey-enc.c:183
#, fuzzy, c-format
msgid "NOTE: cipher algorithm %d not found in preferences\n"
msgstr "nota: algoritmo di cifratura %d non trovato nelle impostazioni\n"
#: g10/seckey-cert.c:56
#, c-format
msgid "protection algorithm %d is not supported\n"
msgstr "l'algoritmo di protezione %d non è gestito\n"
#: g10/seckey-cert.c:169
msgid "Invalid passphrase; please try again ...\n"
msgstr "Passphrase non valida; riprova...\n"
#: g10/seckey-cert.c:216
#, fuzzy
msgid "WARNING: Weak key detected - please change passphrase again.\n"
msgstr ""
"Attenzione: individuata una chiave debole - per favore cambia ancora la\n"
"passphrase.\n"
#: g10/sig-check.c:155
msgid ""
"this is a PGP generated ElGamal key which is NOT secure for signatures!\n"
msgstr ""
"questa è una chiave ElGamal generata da PGP che NON è sicura per le firme!\n"
#: g10/sig-check.c:165
msgid "public key created in future (time warp or clock problem)\n"
msgstr ""
"chiave pubblica creata nel futuro (salto nel tempo o problema con\n"
"l'orologio)\n"
#: g10/sig-check.c:170
#, fuzzy, c-format
msgid "NOTE: signature key expired %s\n"
msgstr "attenzione: firma della chiave scaduta il %s\n"
+#: g10/sig-check.c:226
+msgid "assuming bad signature due to an unknown critical bit\n"
+msgstr ""
+
#: g10/sign.c:69
#, fuzzy, c-format
msgid "%s signature from: %s\n"
msgstr "Firma NON corretta da \""
-#: g10/sign.c:200 g10/sign.c:564
+#: g10/sign.c:200 g10/sign.c:587
#, fuzzy, c-format
msgid "can't create %s: %s\n"
msgstr "%s: impossibile creare: %s\n"
#: g10/sign.c:296
#, fuzzy
msgid "signing:"
msgstr "sign"
#: g10/sign.c:336
#, fuzzy, c-format
msgid "WARNING: '%s' is an empty file\n"
msgstr "%s: attenzione: file vuoto\n"
#: g10/tdbio.c:116 g10/tdbio.c:1413
#, fuzzy, c-format
msgid "trustdb rec %lu: lseek failed: %s\n"
msgstr "aggiornamento della chiave segreta fallito: %s\n"
#: g10/tdbio.c:122 g10/tdbio.c:1420
#, c-format
msgid "trustdb rec %lu: write failed (n=%d): %s\n"
msgstr ""
#: g10/tdbio.c:232
msgid "trustdb transaction to large\n"
msgstr ""
#: g10/tdbio.c:402
#, fuzzy, c-format
msgid "%s: can't access: %s\n"
msgstr "%s: impossibile creare: %s\n"
#: g10/ringedit.c:273 g10/tdbio.c:422
#, fuzzy, c-format
msgid "%s: can't create directory: %s\n"
msgstr "%s: impossibile creare: %s\n"
#: g10/ringedit.c:279 g10/tdbio.c:425
#, fuzzy, c-format
msgid "%s: directory created\n"
msgstr "%s: impossibile creare: %s\n"
#: g10/tdbio.c:429
#, c-format
msgid "%s: directory does not exist!\n"
msgstr ""
#: g10/openfile.c:101 g10/openfile.c:165 g10/ringedit.c:1256 g10/tdbio.c:435
#, c-format
msgid "%s: can't create: %s\n"
msgstr "%s: impossibile creare: %s\n"
#: g10/tdbio.c:459
#, c-format
msgid "%s: failed to create version record: %s"
msgstr ""
#: g10/tdbio.c:463
#, c-format
msgid "%s: invalid trust-db created\n"
msgstr ""
#: g10/tdbio.c:465
#, fuzzy, c-format
msgid "%s: trust-db created\n"
msgstr "%s: impossibile creare: %s\n"
#: g10/tdbio.c:506
#, c-format
msgid "%s: invalid trust-db\n"
msgstr ""
#: g10/tdbio.c:540
#, fuzzy, c-format
msgid "%s: failed to create hashtable: %s\n"
msgstr "%s: impossibile creare: %s\n"
#: g10/tdbio.c:548
#, fuzzy, c-format
msgid "%s: error updating version record: %s\n"
msgstr "%s: errore nel controllare la chiave: %s\n"
#: g10/tdbio.c:564 g10/tdbio.c:603 g10/tdbio.c:628 g10/tdbio.c:1346
#: g10/tdbio.c:1373
#, fuzzy, c-format
msgid "%s: error reading version record: %s\n"
msgstr "%s: errore nel controllare la chiave: %s\n"
#: g10/tdbio.c:577
#, fuzzy, c-format
msgid "%s: error writing version record: %s\n"
msgstr "%s: errore nel controllare la chiave: %s\n"
#: g10/tdbio.c:1053
#, fuzzy, c-format
msgid "trustdb: lseek failed: %s\n"
msgstr "aggiornamento della chiave segreta fallito: %s\n"
#: g10/tdbio.c:1061
#, fuzzy, c-format
msgid "trustdb: read failed (n=%d): %s\n"
msgstr "aggiornamento del trustdb fallito: %s\n"
#: g10/tdbio.c:1082
#, fuzzy, c-format
msgid "%s: not a trustdb file\n"
msgstr "aggiornamento del trustdb fallito: %s\n"
#: g10/tdbio.c:1098
#, c-format
msgid "%s: version record with recnum %lu\n"
msgstr ""
#: g10/tdbio.c:1103
#, fuzzy, c-format
msgid "%s: invalid file version %d\n"
msgstr "header della firma in chiaro non valido\n"
#: g10/tdbio.c:1379
#, fuzzy, c-format
msgid "%s: error reading free record: %s\n"
msgstr "%s: errore nel controllare la chiave: %s\n"
#: g10/tdbio.c:1387
#, fuzzy, c-format
msgid "%s: error writing dir record: %s\n"
msgstr "%s: errore nel controllare la chiave: %s\n"
#: g10/tdbio.c:1397
#, c-format
msgid "%s: failed to zero a record: %s\n"
msgstr ""
#: g10/tdbio.c:1427
#, c-format
msgid "%s: failed to append a record: %s\n"
msgstr ""
-#: g10/trustdb.c:134
+#: g10/trustdb.c:142
msgid "The trust DB is corrupted; please run \"gpgm --fix-trust-db\".\n"
msgstr "Il trustdb è rovinato; per favore esegui \"gpgm --fix-trust-db\".\n"
-#: g10/trustdb.c:147
+#: g10/trustdb.c:155
#, c-format
msgid "trust record %lu, req type %d: read failed: %s\n"
msgstr ""
-#: g10/trustdb.c:162
+#: g10/trustdb.c:170
#, c-format
msgid "trust record %lu, type %d: write failed: %s\n"
msgstr ""
-#: g10/trustdb.c:176
+#: g10/trustdb.c:184
#, fuzzy, c-format
msgid "trust record %lu: delete failed: %s\n"
msgstr "aggiornamento della chiave segreta fallito: %s\n"
-#: g10/trustdb.c:190
+#: g10/trustdb.c:198
#, fuzzy, c-format
msgid "trust db: sync failed: %s\n"
msgstr "aggiornamento del trustdb fallito: %s\n"
-#: g10/trustdb.c:319
+#: g10/trustdb.c:327
#, c-format
msgid "error reading dir record for LID %lu: %s\n"
msgstr ""
-#: g10/trustdb.c:326
+#: g10/trustdb.c:334
#, c-format
msgid "lid %lu: expected dir record, got type %d\n"
msgstr ""
-#: g10/trustdb.c:331
+#: g10/trustdb.c:339
#, c-format
msgid "no primary key for LID %lu\n"
msgstr ""
-#: g10/trustdb.c:336
+#: g10/trustdb.c:344
#, fuzzy, c-format
msgid "error reading primary key for LID %lu: %s\n"
msgstr "errore nella creazione della passhprase: %s\n"
-#: g10/trustdb.c:412
+#: g10/trustdb.c:420
#, c-format
msgid "chained sigrec %lu has a wrong owner\n"
msgstr "la chained sigrec %lu ha il proprietario sbagliato\n"
-#: g10/trustdb.c:455
+#: g10/trustdb.c:463
#, fuzzy, c-format
msgid "'%s' is not a valid long keyID\n"
msgstr "Carattere non valido nel commento\n"
-#: g10/trustdb.c:490
+#: g10/trustdb.c:498
#, fuzzy, c-format
msgid "key %08lX: no public key for trusted key - skipped\n"
msgstr "chiave %08lX: chiave segreta senza chiave pubblica - saltata\n"
-#: g10/trustdb.c:499 g10/trustdb.c:557
+#: g10/trustdb.c:507 g10/trustdb.c:565
#, c-format
msgid "key %08lX: can't put it into the trustdb\n"
msgstr "chiave %08lX: impossibile metterla nel trustdb\n"
-#: g10/trustdb.c:504 g10/trustdb.c:563
+#: g10/trustdb.c:512 g10/trustdb.c:571
#, c-format
msgid "key %08lX: query record failed\n"
msgstr "chiave %08lX: richiesta del record fallita\n"
-#: g10/trustdb.c:509 g10/trustdb.c:572
+#: g10/trustdb.c:517 g10/trustdb.c:580
#, fuzzy, c-format
msgid "key %08lX: already in trusted key table\n"
msgstr "chiave %08lX: già nella tabella delle chiavi segrete\n"
-#: g10/trustdb.c:512 g10/trustdb.c:575
+#: g10/trustdb.c:520 g10/trustdb.c:583
#, fuzzy, c-format
msgid "key %08lX: accepted as trusted key.\n"
msgstr "chiave %08lX: accettata come chiave segreta\n"
-#: g10/trustdb.c:528
+#: g10/trustdb.c:536
#, fuzzy, c-format
msgid "NOTE: secret key %08lX is NOT protected.\n"
msgstr "Questa chiave non è protetta.\n"
-#: g10/trustdb.c:540
+#: g10/trustdb.c:548
#, c-format
msgid "key %08lX: secret key without public key - skipped\n"
msgstr "chiave %08lX: chiave segreta senza chiave pubblica - saltata\n"
-#: g10/trustdb.c:547
+#: g10/trustdb.c:555
#, c-format
msgid "key %08lX: secret and public key don't match\n"
msgstr "chiave %08lX: le chiavi segreta e pubblica non corrispondono\n"
-#: g10/trustdb.c:583
+#: g10/trustdb.c:591
#, fuzzy, c-format
msgid "enumerate secret keys failed: %s\n"
msgstr "enum_secret_keys fallito: %s\n"
-#: g10/trustdb.c:766
+#: g10/trustdb.c:774
#, fuzzy, c-format
msgid "lid %lu: read dir record failed: %s\n"
msgstr "chiave %08lX: inserimento del record della fiducia fallito: %s\n"
-#: g10/trustdb.c:775
+#: g10/trustdb.c:783
#, fuzzy, c-format
msgid "lid %lu: read key record failed: %s\n"
msgstr "chiave %08lX: inserimento del record della fiducia fallito: %s\n"
-#: g10/trustdb.c:785
+#: g10/trustdb.c:793
#, fuzzy, c-format
msgid "lid %lu: read uid record failed: %s\n"
msgstr "chiave %08lX: inserimento del record della fiducia fallito: %s\n"
-#: g10/trustdb.c:794
+#: g10/trustdb.c:802
#, fuzzy, c-format
msgid "lid %lu: read pref record failed: %s\n"
msgstr "chiave %08lX: inserimento del record della fiducia fallito: %s\n"
-#: g10/trustdb.c:804
+#: g10/trustdb.c:812
#, fuzzy, c-format
msgid "lid %lu: read sig record failed: %s\n"
msgstr "chiave %08lX: inserimento del record della fiducia fallito: %s\n"
-#: g10/trustdb.c:999
+#: g10/trustdb.c:1013
msgid "Ooops, no keys\n"
msgstr ""
-#: g10/trustdb.c:1003
+#: g10/trustdb.c:1017
#, fuzzy
msgid "Ooops, no user ids\n"
msgstr "elenca le chiavi e gli user id"
-#: g10/trustdb.c:1074 g10/trustdb.c:1092
+#: g10/trustdb.c:1088 g10/trustdb.c:1106
#, c-format
msgid "user '%s' read problem: %s\n"
msgstr ""
-#: g10/trustdb.c:1077 g10/trustdb.c:1095
+#: g10/trustdb.c:1091 g10/trustdb.c:1109
#, c-format
msgid "user '%s' list problem: %s\n"
msgstr ""
-#: g10/trustdb.c:1085 g10/trustdb.c:1300
+#: g10/trustdb.c:1099 g10/trustdb.c:1346
#, fuzzy, c-format
msgid "user '%s' not found: %s\n"
msgstr "%s: utente non trovato\n"
-#: g10/trustdb.c:1087 g10/trustdb.c:1302
+#: g10/trustdb.c:1101 g10/trustdb.c:1348
#, c-format
msgid "problem finding '%s' in trustdb: %s\n"
msgstr ""
-#: g10/trustdb.c:1090
+#: g10/trustdb.c:1104
#, c-format
msgid "user '%s' not in trustdb\n"
msgstr ""
-#: g10/trustdb.c:1125
+#: g10/trustdb.c:1139
#, c-format
msgid ""
"# List of assigned trustvalues, created %s\n"
"# (Use \"gpgm --import-ownertrust\" to restore them)\n"
msgstr ""
-#: g10/trustdb.c:1131
+#: g10/trustdb.c:1145
msgid "directory record w/o primary key\n"
msgstr ""
-#: g10/trustdb.c:1138
+#: g10/trustdb.c:1152
#, fuzzy, c-format
msgid "error reading key record: %s\n"
msgstr "%s: errore nel controllare la chiave: %s\n"
-#: g10/trustdb.c:1178
+#: g10/trustdb.c:1192
msgid "line too long\n"
msgstr ""
-#: g10/trustdb.c:1186
+#: g10/trustdb.c:1200
msgid "error: missing colon\n"
msgstr ""
-#: g10/trustdb.c:1191
+#: g10/trustdb.c:1205
#, fuzzy
msgid "error: invalid fingerprint\n"
msgstr "errore nella riga della coda\n"
-#: g10/trustdb.c:1195
+#: g10/trustdb.c:1209
#, fuzzy
msgid "error: no ownertrust value\n"
msgstr "esporta i valori di fiducia"
-#: g10/trustdb.c:1209
+#: g10/trustdb.c:1223
#, c-format
msgid "LID %lu: changing trust from %u to %u\n"
msgstr ""
-#: g10/trustdb.c:1212
+#: g10/trustdb.c:1226
#, c-format
msgid "LID %lu: setting trust to %u\n"
msgstr ""
-#: g10/trustdb.c:1220
+#: g10/trustdb.c:1234
msgid "key not in trustdb, searching ring.\n"
msgstr ""
-#: g10/trustdb.c:1223
+#: g10/trustdb.c:1237
#, fuzzy, c-format
msgid "key not in ring: %s\n"
msgstr "impossibile scrivere il portachiavi: %s\n"
-#: g10/trustdb.c:1227
+#: g10/trustdb.c:1241
msgid "Oops: key is now in trustdb???\n"
msgstr ""
#. update the ownertrust
-#: g10/trustdb.c:1232
+#: g10/trustdb.c:1246
#, fuzzy, c-format
msgid "insert trust record failed: %s\n"
msgstr "chiave %08lX: inserimento del record della fiducia fallito: %s\n"
#. error
-#: g10/trustdb.c:1238
+#: g10/trustdb.c:1252
#, fuzzy, c-format
msgid "error finding dir record: %s\n"
msgstr "rimozione dell'armatura fallita: %s\n"
-#: g10/trustdb.c:1305
+#: g10/trustdb.c:1351
#, c-format
msgid "user '%s' not in trustdb - inserting\n"
msgstr ""
-#: g10/trustdb.c:1308
+#: g10/trustdb.c:1354
#, fuzzy, c-format
msgid "failed to put '%s' into trustdb: %s\n"
msgstr "inizializzazione del trustdb fallita: %s\n"
-#: g10/trustdb.c:1355
+#: g10/trustdb.c:1404
#, c-format
msgid "%s: keyblock read problem: %s\n"
msgstr ""
-#: g10/trustdb.c:1369
+#: g10/trustdb.c:1418
#, fuzzy, c-format
msgid "%s: update failed: %s\n"
msgstr "aggiornamento fallito: %s\n"
-#: g10/trustdb.c:1372
+#: g10/trustdb.c:1421
#, fuzzy, c-format
msgid "%s: updated\n"
msgstr "\\t%lu chiavi aggiornate\n"
-#: g10/trustdb.c:1374
+#: g10/trustdb.c:1423
#, c-format
msgid "%s: okay\n"
msgstr ""
-#: g10/trustdb.c:1389
+#: g10/trustdb.c:1438
#, c-format
msgid "lid %lu: dir record w/o key - skipped\n"
msgstr ""
-#: g10/trustdb.c:1402
+#: g10/trustdb.c:1451
#, fuzzy, c-format
msgid "lid %lu: keyblock not found: %s\n"
msgstr "chiave %08lX: chiave pubblica non trovata: %s\n"
-#: g10/trustdb.c:1411 g10/trustdb.c:1480
+#: g10/trustdb.c:1460 g10/trustdb.c:1529
#, fuzzy, c-format
msgid "lid %lu: update failed: %s\n"
msgstr "aggiornamento fallito: %s\n"
-#: g10/trustdb.c:1417 g10/trustdb.c:1486
+#: g10/trustdb.c:1466 g10/trustdb.c:1535
#, fuzzy, c-format
msgid "lid %lu: updated\n"
msgstr "\\t%lu chiavi aggiornate\n"
-#: g10/trustdb.c:1421 g10/trustdb.c:1490
+#: g10/trustdb.c:1470 g10/trustdb.c:1539
#, fuzzy, c-format
msgid "lid %lu: okay\n"
msgstr "lid %lu: manca la chiave primaria\n"
-#: g10/trustdb.c:1428 g10/trustdb.c:1496
+#: g10/trustdb.c:1477 g10/trustdb.c:1545
#, c-format
msgid "%lu keys processed\n"
msgstr "%lu chiavi esaminate\n"
-#: g10/trustdb.c:1430
+#: g10/trustdb.c:1479
#, c-format
msgid "\t%lu keys skipped\n"
msgstr "\\t%lu chiavi saltate\n"
-#: g10/trustdb.c:1432 g10/trustdb.c:1498
+#: g10/trustdb.c:1481 g10/trustdb.c:1547
#, c-format
msgid "\t%lu keys with errors\n"
msgstr "\\t%lu chiavi con errori\n"
-#: g10/trustdb.c:1434 g10/trustdb.c:1500
+#: g10/trustdb.c:1483 g10/trustdb.c:1549
#, c-format
msgid "\t%lu keys updated\n"
msgstr "\\t%lu chiavi aggiornate\n"
-#: g10/trustdb.c:1464
+#: g10/trustdb.c:1513
#, fuzzy, c-format
msgid "lid ?: insert failed: %s\n"
msgstr "aggiornamento della chiave segreta fallito: %s\n"
-#: g10/trustdb.c:1469
+#: g10/trustdb.c:1518
#, fuzzy, c-format
msgid "lid %lu: insert failed: %s\n"
msgstr "aggiornamento della chiave segreta fallito: %s\n"
-#: g10/trustdb.c:1475
+#: g10/trustdb.c:1524
#, fuzzy, c-format
msgid "lid %lu: inserted\n"
msgstr "\\t%lu chiavi inserite\n"
-#: g10/trustdb.c:1502
+#: g10/trustdb.c:1551
#, c-format
msgid "\t%lu keys inserted\n"
msgstr "\\t%lu chiavi inserite\n"
-#: g10/trustdb.c:1505
+#: g10/trustdb.c:1554
#, fuzzy, c-format
msgid "enumerate keyblocks failed: %s\n"
msgstr "enum_secret_keys fallito: %s\n"
-#: g10/trustdb.c:1550
+#: g10/trustdb.c:1599
#, fuzzy, c-format
msgid "check_trust: search dir record failed: %s\n"
msgstr "chiave %08lX: inserimento del record della fiducia fallito: %s\n"
-#: g10/trustdb.c:1557
+#: g10/trustdb.c:1606
#, c-format
msgid "key %08lX: insert trust record failed: %s\n"
msgstr "chiave %08lX: inserimento del record della fiducia fallito: %s\n"
-#: g10/trustdb.c:1561
+#: g10/trustdb.c:1610
#, c-format
msgid "key %08lX.%lu: inserted into trustdb\n"
msgstr "chiave %08lX.%lu: inserita nel trustdb\n"
-#: g10/trustdb.c:1569
+#: g10/trustdb.c:1618
#, c-format
msgid "key %08lX.%lu: created in future (time warp or clock problem)\n"
msgstr ""
"chiave %08lX.%lu: creata nel futuro (salto nel tempo o problema\n"
"con l'orologio)\n"
-#: g10/trustdb.c:1576
+#: g10/trustdb.c:1625
#, c-format
msgid "key %08lX.%lu: expired at %s\n"
msgstr "chiave %08lX.%lu: scaduta il %s\n"
-#: g10/trustdb.c:1584
+#: g10/trustdb.c:1633
#, c-format
msgid "key %08lX.%lu: trust check failed: %s\n"
msgstr "chiave %08lX.%lu: controllo della fiducia fallito: %s\n"
-#: g10/trustdb.c:1753 g10/trustdb.c:1782 g10/trustdb.c:2521
+#: g10/trustdb.c:1820 g10/trustdb.c:1849 g10/trustdb.c:2588
msgid "WARNING: can't yet handle long pref records\n"
msgstr ""
-#: g10/trustdb.c:1804
+#: g10/trustdb.c:1871
#, fuzzy, c-format
msgid "get_dir_record: search_record failed: %s\n"
msgstr "aggiornamento della chiave segreta fallito: %s\n"
-#: g10/trustdb.c:1867
+#: g10/trustdb.c:1934
#, fuzzy, c-format
msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but marked as checked\n"
msgstr ""
"nota: rec di %lu[%d] nella hintlist di %lu ma marcato come verificato\n"
-#: g10/trustdb.c:1871
+#: g10/trustdb.c:1938
#, fuzzy, c-format
msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but not marked\n"
msgstr "nota: rec di %lu[%d] nella hintlist di %lu ma non marcato\n"
#. we need the dir record
-#: g10/trustdb.c:1878
+#: g10/trustdb.c:1945
#, c-format
msgid "sig rec %lu[%d] in hintlist of %lu does not point to a dir record\n"
msgstr "Il rec di %lu[%d] nella hintlist di %lu non punta a un record dir\n"
-#: g10/trustdb.c:1884
+#: g10/trustdb.c:1951
#, c-format
msgid "lid %lu: no primary key\n"
msgstr "lid %lu: manca la chiave primaria\n"
-#: g10/trustdb.c:1917
+#: g10/trustdb.c:1984
#, c-format
msgid "lid %lu: user id not found in keyblock\n"
msgstr "lid %lu: user id non trovato nel keyblock\n"
-#: g10/trustdb.c:1921
+#: g10/trustdb.c:1988
#, c-format
msgid "lid %lu: user id without signature\n"
msgstr "chiave %08lX: user id senza firma\n"
-#: g10/trustdb.c:1928
+#: g10/trustdb.c:1995
#, c-format
msgid "lid %lu: self-signature in hintlist\n"
msgstr "lid %lu: autofirma nella hintlist\n"
-#: g10/trustdb.c:1939 g10/trustdb.c:2658 g10/trustdb.c:2742
+#: g10/trustdb.c:2006 g10/trustdb.c:2725 g10/trustdb.c:2809
msgid "Valid certificate revocation"
msgstr "Revoca del certificato valida"
-#: g10/trustdb.c:1940 g10/trustdb.c:2659 g10/trustdb.c:2743
+#: g10/trustdb.c:2007 g10/trustdb.c:2726 g10/trustdb.c:2810
msgid "Good certificate"
msgstr "Certificato corretto"
-#: g10/trustdb.c:1949
+#: g10/trustdb.c:2016
msgid "very strange: no public key\n"
msgstr "molto strano: non ci sono chiavi pubbliche\n"
-#: g10/trustdb.c:1997
+#: g10/trustdb.c:2064
#, c-format
msgid "hintlist %lu[%d] of %lu does not point to a dir record\n"
msgstr "hintlist %lu[%d] di %lu non punta a un record dir\n"
-#: g10/trustdb.c:2003
+#: g10/trustdb.c:2070
#, c-format
msgid "lid %lu does not have a key\n"
msgstr "Il lid %lu non ha una chiave\n"
-#: g10/trustdb.c:2013
+#: g10/trustdb.c:2080
#, c-format
msgid "lid %lu: can't get keyblock: %s\n"
msgstr "lid %lu: impossibile ottenere il keyblock: %s\n"
-#: g10/trustdb.c:2070 g10/trustdb.c:2984
+#: g10/trustdb.c:2137 g10/trustdb.c:3051
#, fuzzy, c-format
msgid "tdbio_search_dir failed: %s\n"
msgstr "rimozione dell'armatura fallita: %s\n"
-#: g10/trustdb.c:2223
+#: g10/trustdb.c:2290
#, c-format
msgid "key %08lX.%lu: Good subkey binding\n"
msgstr "chiave %08lX.%lu: Legame con la subchiave corretto\n"
-#: g10/trustdb.c:2229 g10/trustdb.c:2271
+#: g10/trustdb.c:2296 g10/trustdb.c:2338
#, c-format
msgid "key %08lX.%lu: Invalid subkey binding: %s\n"
msgstr "chiave %08lX.%lu: Legame con la subchiave non valido: %s\n"
-#: g10/trustdb.c:2244
+#: g10/trustdb.c:2311
#, c-format
msgid "key %08lX.%lu: Valid key revocation\n"
msgstr "chiave %08lX.%lu: Revoca della chiave valida\n"
-#: g10/trustdb.c:2250
+#: g10/trustdb.c:2317
#, c-format
msgid "key %08lX.%lu: Invalid key revocation: %s\n"
msgstr "chiave %08lX.%lu: Revoca della chiave non valida: %s\n"
-#: g10/trustdb.c:2265
+#: g10/trustdb.c:2332
#, c-format
msgid "key %08lX.%lu: Valid subkey revocation\n"
msgstr "chiave %08lX.%lu: Revoca della subchiave valida\n"
-#: g10/trustdb.c:2365
+#: g10/trustdb.c:2432
msgid "Good self-signature"
msgstr "Autofirma corretta"
-#: g10/trustdb.c:2376
+#: g10/trustdb.c:2443
msgid "Invalid self-signature"
msgstr "Autofirma non valida"
-#: g10/trustdb.c:2386
+#: g10/trustdb.c:2453
msgid "Valid user ID revocation skipped due to a newer self signature\n"
msgstr ""
-#: g10/trustdb.c:2393
+#: g10/trustdb.c:2460
msgid "Valid user ID revocation\n"
msgstr "Revoca dell'user ID valida\n"
-#: g10/trustdb.c:2400
+#: g10/trustdb.c:2467
msgid "Invalid user ID revocation"
msgstr "Revoca dell'user ID non valida"
-#: g10/trustdb.c:2484
+#: g10/trustdb.c:2551
msgid "Too many preferences"
msgstr "Troppe preferenze"
-#: g10/trustdb.c:2498
+#: g10/trustdb.c:2565
#, fuzzy
msgid "Too many preference items"
msgstr "Troppi elementi di preferenza"
-#: g10/trustdb.c:2637
+#: g10/trustdb.c:2704
msgid "Duplicated certificate - deleted"
msgstr "Certificato doppio - cancellato"
-#: g10/trustdb.c:2670
+#: g10/trustdb.c:2737
#, fuzzy
msgid "Hmmm, public key lost?"
msgstr "chiave pubblica perduta"
-#: g10/trustdb.c:2680 g10/trustdb.c:2763
+#: g10/trustdb.c:2747 g10/trustdb.c:2830
msgid "Invalid certificate revocation"
msgstr "Certificato di revoca non valido"
-#: g10/trustdb.c:2681 g10/trustdb.c:2764
+#: g10/trustdb.c:2748 g10/trustdb.c:2831
msgid "Invalid certificate"
msgstr "Certificato non valido"
-#: g10/trustdb.c:2696
+#: g10/trustdb.c:2763
#, c-format
msgid "uid %08lX.%lu/%02X%02X: has shadow dir %lu but is not yet marked.\n"
msgstr ""
-#: g10/trustdb.c:2710
+#: g10/trustdb.c:2777
#, fuzzy, c-format
msgid "sig record %lu[%d] points to wrong record.\n"
msgstr "Il rec di %lu[%d] nella hintlist di %lu non punta a un record dir\n"
#. that should never happen
-#: g10/trustdb.c:2954
+#: g10/trustdb.c:3021
#, fuzzy, c-format
msgid "insert_trust_record: keyblock not found: %s\n"
msgstr "chiave %08lX: chiave segreta non trovata: %s\n"
-#: g10/trustdb.c:2972
+#: g10/trustdb.c:3039
msgid "did not use primary key for insert_trust_record()\n"
msgstr ""
#: g10/ringedit.c:293
#, fuzzy, c-format
msgid "%s: can't create keyring: %s\n"
msgstr "%s: impossibile creare: %s\n"
#: g10/ringedit.c:299 g10/ringedit.c:1264
#, fuzzy, c-format
msgid "%s: keyring created\n"
msgstr "%s: creato un nuovo file delle opzioni\n"
#: g10/ringedit.c:1449
msgid "WARNING: 2 files with confidential information exists.\n"
msgstr ""
#: g10/ringedit.c:1450
#, fuzzy, c-format
msgid "%s is the unchanged one\n"
msgstr "chiavi segrete non cambiate %lu\n"
#: g10/ringedit.c:1451
#, c-format
msgid "%s is the new one\n"
msgstr ""
#: g10/ringedit.c:1452
msgid "Please fix this possible security flaw\n"
msgstr ""
#: g10/skclist.c:94
#, fuzzy, c-format
msgid "skipped '%s': %s\n"
msgstr "%s: saltata: %s\n"
#: g10/skclist.c:100
#, fuzzy, c-format
msgid ""
"skipped '%s': this is a PGP generated ElGamal key which is not secure for "
"signatures!\n"
msgstr ""
"questa è una chiave ElGamal generata da PGP che NON è sicura per le firme!\n"
#. do not overwrite
#: g10/openfile.c:58
#, c-format
msgid "File '%s' exists. "
msgstr "Il file '%s' esiste. "
#: g10/openfile.c:60
msgid "Overwrite (y/N)? "
msgstr "Sovrascrivo (y/N)? "
#: g10/openfile.c:85
msgid "writing to stdout\n"
msgstr "scrivo su stdout\n"
#: g10/openfile.c:134
#, c-format
msgid "assuming signed data in '%s'\n"
msgstr "presumo che i dati firmati siano in '%s'\n"
#: g10/openfile.c:181
#, c-format
msgid "%s: new options file created\n"
msgstr "%s: creato un nuovo file delle opzioni\n"
#: g10/encr-data.c:59
#, fuzzy, c-format
msgid "%s encrypted data\n"
msgstr "cifra dati"
#: g10/encr-data.c:61
#, c-format
msgid "encrypted with unknown algorithm %d\n"
msgstr ""
#: g10/encr-data.c:74
#, fuzzy
msgid ""
"WARNING: Message was encrypted with a weak key in the symmetric cipher.\n"
msgstr ""
"Attenzione: il messaggio era stato crittografato usando una chiave debole\n"
"per il cifrario simmetrico\n"
#: g10/seskey.c:52
msgid "weak key created - retrying\n"
msgstr "creata una chiave debole - riprovo\n"
#: g10/seskey.c:57
#, c-format
msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n"
msgstr ""
"Impossibile evitare una chiave debole per il cifrario simmetrico;\n"
"ho provato %d volte!\n"
#. begin of list
-#: g10/helptext.c:45
+#: g10/helptext.c:48
msgid "edit_ownertrust.value"
msgstr "edit_ownertrust.value"
-#: g10/helptext.c:51
+#: g10/helptext.c:54
msgid "revoked_key.override"
msgstr "revoked_key.override"
-#: g10/helptext.c:55
+#: g10/helptext.c:58
msgid "untrusted_key.override"
msgstr "untrusted_key.override"
-#: g10/helptext.c:59
+#: g10/helptext.c:62
msgid "pklist.user_id.enter"
msgstr "pklist.user_id.enter"
-#: g10/helptext.c:63
+#: g10/helptext.c:66
msgid "keygen.algo"
msgstr "keygen.algo"
-#: g10/helptext.c:79
+#: g10/helptext.c:82
#, fuzzy
msgid "keygen.algo.elg_se"
msgstr "keygen.algo"
-#: g10/helptext.c:86
+#: g10/helptext.c:89
msgid "keygen.size"
msgstr "keygen.size"
-#: g10/helptext.c:90
+#: g10/helptext.c:93
msgid "keygen.size.huge.okay"
msgstr "keygen.size.huge.okay"
-#: g10/helptext.c:95
+#: g10/helptext.c:98
msgid "keygen.size.large.okay"
msgstr "keygen.size.large.okay"
-#: g10/helptext.c:100
+#: g10/helptext.c:103
msgid "keygen.valid"
msgstr "keygen.valid"
-#: g10/helptext.c:104
+#: g10/helptext.c:107
msgid "keygen.valid.okay"
msgstr "keygen.valid.okay"
-#: g10/helptext.c:109
+#: g10/helptext.c:112
msgid "keygen.name"
msgstr "keygen.name"
-#: g10/helptext.c:114
+#: g10/helptext.c:117
msgid "keygen.email"
msgstr "keygen.email"
-#: g10/helptext.c:118
+#: g10/helptext.c:121
msgid "keygen.comment"
msgstr "keygen.comment"
-#: g10/helptext.c:123
+#: g10/helptext.c:126
msgid "keygen.userid.cmd"
msgstr "keygen.userid.cmd"
-#: g10/helptext.c:132
+#: g10/helptext.c:135
msgid "keygen.sub.okay"
msgstr "keygen.sub.okay"
-#: g10/helptext.c:136
+#: g10/helptext.c:139
msgid "sign_uid.okay"
msgstr "sign_uid.okay"
-#: g10/helptext.c:141
+#: g10/helptext.c:144
msgid "change_passwd.empty.okay"
msgstr "change_passwd.empty.okay"
-#: g10/helptext.c:146
+#: g10/helptext.c:149
msgid "keyedit.cmd"
msgstr "keyedit.cmd"
-#: g10/helptext.c:150
+#: g10/helptext.c:153
msgid "keyedit.save.okay"
msgstr "keyedit.save.okay"
-#: g10/helptext.c:155
+#: g10/helptext.c:158
msgid "keyedit.cancel.okay"
msgstr "keyedit.cancel.okay"
-#: g10/helptext.c:159
+#: g10/helptext.c:162
msgid "keyedit.sign_all.okay"
msgstr "keyedit.sign_all.okay"
-#: g10/helptext.c:163
+#: g10/helptext.c:166
msgid "keyedit.remove.uid.okay"
msgstr "keyedit.remove.uid.okay"
-#: g10/helptext.c:168
+#: g10/helptext.c:171
msgid "keyedit.remove.subkey.okay"
msgstr "keyedit.remove.subkey.okay"
-#: g10/helptext.c:172
+#: g10/helptext.c:175
msgid "passphrase.enter"
msgstr "passphrase.enter"
-#: g10/helptext.c:179
+#: g10/helptext.c:182
msgid "passphrase.repeat"
msgstr "passphrase.repeat"
-#: g10/helptext.c:183
+#: g10/helptext.c:186
msgid "detached_signature.filename"
msgstr "detached_signature.filename"
-#: g10/helptext.c:187
+#: g10/helptext.c:190
msgid "openfile.overwrite.okay"
msgstr "openfile.overwrite.okay"
-#: g10/helptext.c:201
+#: g10/helptext.c:204
msgid "No help available"
msgstr "Nessun aiuto disponibile"
-#: g10/helptext.c:213
+#: g10/helptext.c:216
#, c-format
msgid "No help available for '%s'"
msgstr "Nessun aiuto disponibile per '%s'"
#~ msgid "You will see a list of signators etc. here\n"
#~ msgstr "Qui vedrai una lista di firmatari, ecc.\n"
diff --git a/po/pt_BR.po b/po/pt_BR.po
index a68a39607..ac40974d8 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -1,3067 +1,3081 @@
# Portuguese messages for gnupg
# Thiago Jung Bauermann <jungmann@usa.net>, 1998.
# I tried to make this one close to es_ES by Urko Lusa
#
msgid ""
msgstr ""
-"POT-Creation-Date: 1998-12-10 20:11+0100\n"
+"POT-Creation-Date: 1998-12-17 18:30+0100\n"
"Content-Type: text/plain; charset=iso-8859-1\n"
"Date: 1998-11-20 23:46:36-0200\n"
"From: Thiago Jung Bauermann <jungmann@usa.net>\n"
"Xgettext-Options: --default-domain=gnupg --directory=.. --add-comments "
"--keyword=_ --keyword=N_ --files-from=./POTFILES.in\n"
"Files: util/secmem.c util/argparse.c cipher/random.c cipher/rand-dummy.c "
"cipher/rand-unix.c cipher/rand-w32.c g10/g10.c g10/pkclist.c g10/keygen.c "
"g10/decrypt.c g10/encode.c g10/import.c g10/keyedit.c g10/keylist.c "
"g10/mainproc.c g10/passphrase.c g10/plaintext.c g10/pref.c g10/seckey-cert.c "
"g10/sig-check.c g10/sign.c g10/trustdb.c g10/verify.c\n"
#: util/secmem.c:77
msgid "Warning: using insecure memory!\n"
msgstr "Aviso: usando memória insegura!\n"
#: util/miscutil.c:143
msgid "yes"
msgstr "sim"
#: util/miscutil.c:144
msgid "yY"
msgstr "sS"
#: util/errors.c:54
msgid "General error"
msgstr "Erro geral"
#: util/errors.c:55
msgid "Unknown packet type"
msgstr "Formato desconhecido"
#: util/errors.c:56
msgid "Unknown version"
msgstr "Versão desconhecida"
#: util/errors.c:57
msgid "Unknown pubkey algorithm"
msgstr "Algoritmo de chave pública desconhecido"
#: util/errors.c:58
msgid "Unknown digest algorithm"
msgstr "Algoritmo de \"digest\" desconhecido"
#: util/errors.c:59
msgid "Bad public key"
msgstr "Chave pública incorreta"
#: util/errors.c:60
msgid "Bad secret key"
msgstr "Chave secreta incorreta"
#: util/errors.c:61
msgid "Bad signature"
msgstr "Assinatura incorreta"
#: util/errors.c:62
msgid "Checksum error"
msgstr "Erro de \"checksum\""
#: util/errors.c:63
msgid "Bad passphrase"
msgstr "Frase secreta incorreta"
#: util/errors.c:64
msgid "Public key not found"
msgstr "Chave pública não encontrada"
#: util/errors.c:65
msgid "Unknown cipher algorithm"
msgstr "Algoritmo de criptografia desconhecido"
#: util/errors.c:66
msgid "Can't open the keyring"
msgstr "Não é possível abrir o anel de chaves"
#: util/errors.c:67
msgid "Invalid packet"
msgstr "Valor inválido"
#: util/errors.c:68
msgid "Invalid armor"
msgstr "Armadura inválida"
#: util/errors.c:69
msgid "No such user id"
msgstr "Identificador de usuário inexistente"
#: util/errors.c:70
msgid "Secret key not available"
msgstr "Chave secreta não disponível"
#: util/errors.c:71
msgid "Wrong secret key used"
msgstr "Chave secreta incorreta"
#: util/errors.c:72
msgid "Not supported"
msgstr "Não suportado"
#: util/errors.c:73
msgid "Bad key"
msgstr "Chave incorreta"
#: util/errors.c:74
msgid "File read error"
msgstr "Erro de leitura"
#: util/errors.c:75
msgid "File write error"
msgstr "Erro de escrita"
#: util/errors.c:76
msgid "Unknown compress algorithm"
msgstr "Algoritmo de compressão desconhecido"
#: util/errors.c:77
msgid "File open error"
msgstr "Erro abrindo arquivo"
#: util/errors.c:78
msgid "File create error"
msgstr "Erro criando arquivo"
#: util/errors.c:79
msgid "Invalid passphrase"
msgstr "Frase secreta inválida"
#: util/errors.c:80
msgid "Unimplemented pubkey algorithm"
msgstr "Algoritmo de chave pública não implementado"
#: util/errors.c:81
msgid "Unimplemented cipher algorithm"
msgstr "Algoritmo de criptografia não implementado"
#: util/errors.c:82
msgid "Unknown signature class"
msgstr "Classe de assinatura desconhecida"
#: util/errors.c:83
msgid "Trust database error"
msgstr "Erro no banco de dados de confiança"
#: util/errors.c:84
msgid "Bad MPI"
msgstr "MPI incorreto"
#: util/errors.c:85
msgid "Resource limit"
msgstr "Limite de recurso"
#: util/errors.c:86
msgid "Invalid keyring"
msgstr "Anel de chaves inválido"
#: util/errors.c:87
msgid "Bad certificate"
msgstr "Certificado incorreto"
#: util/errors.c:88
msgid "Malformed user id"
msgstr "Identificação de usuário mal formada"
#: util/errors.c:89
msgid "File close error"
msgstr "Erro fechando arquivo"
#: util/errors.c:90
msgid "File rename error"
msgstr "Erro renomeando arquivo"
#: util/errors.c:91
msgid "File delete error"
msgstr "Erro deletando arquivo"
#: util/errors.c:92
msgid "Unexpected data"
msgstr "Dados inesperados"
#: util/errors.c:93
msgid "Timestamp conflict"
msgstr "Conflito com \"timestamp\""
#: util/errors.c:94
msgid "Unusable pubkey algorithm"
msgstr "Algoritmo de chave pública inutilizável"
#: util/errors.c:95
msgid "File exists"
msgstr "O arquivo já existe"
#: util/errors.c:96
msgid "Weak key"
msgstr "Chave fraca"
#: util/logger.c:178
#, c-format
msgid "... this is a bug (%s:%d:%s)\n"
msgstr "... isto é um bug (%s:%d:%s)\n"
#: util/logger.c:184
#, c-format
msgid "you found a bug ... (%s:%d)\n"
msgstr "você encontrou um bug ... (%s:%d)\n"
-#: cipher/random.c:412
+#: cipher/random.c:406
msgid "WARNING: using insecure random number generator!!\n"
msgstr "AVISO: usando gerador de números aleatórios inseguro!\n"
-#: cipher/random.c:413
+#: cipher/random.c:407
msgid ""
"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"
msgstr ""
"O gerador de números aleatórios é apenas um \"remendo\"\n"
"para poder compilar - Ele não é seguro!\n"
"\n"
"NÃO USE NENHUM DADO GERADO POR ESTE PROGRAMA!\n"
"\n"
-#: cipher/rndlinux.c:116
+#: cipher/rndlinux.c:118
#, c-format
msgid ""
"\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"
msgstr ""
"\n"
"Não há bytes aleatórios suficientes. Por favor, faça algum outro trabalho\n"
"para que o sistema possa coletar mais entropia!\n"
"(São necessários mais %d bytes)\n"
-#: g10/g10.c:159
+#: g10/g10.c:160
msgid ""
"@Commands:\n"
" "
msgstr ""
"@Comandos:\n"
" "
-#: g10/g10.c:162
+#: g10/g10.c:163
msgid "|[file]|make a signature"
msgstr "|[arquivo]|faz uma assinatura"
-#: g10/g10.c:163
+#: g10/g10.c:164
msgid "|[file]|make a clear text signature"
msgstr "|[arquivo]|faz uma assinatura em texto puro"
-#: g10/g10.c:164
+#: g10/g10.c:165
msgid "make a detached signature"
msgstr "faz uma assinatura separada"
-#: g10/g10.c:165
+#: g10/g10.c:166
msgid "encrypt data"
msgstr "codifica dados"
-#: g10/g10.c:166
+#: g10/g10.c:167
msgid "encryption only with symmetric cipher"
msgstr "codifica apenas com criptografia simétrica"
-#: g10/g10.c:167
+#: g10/g10.c:168
msgid "store only"
msgstr "apenas armazena"
-#: g10/g10.c:168
+#: g10/g10.c:169
msgid "decrypt data (default)"
msgstr "decodifica dados (padrão)"
-#: g10/g10.c:169
+#: g10/g10.c:170
msgid "verify a signature"
msgstr "verifica uma assinatura"
-#: g10/g10.c:171
+#: g10/g10.c:172
msgid "list keys"
msgstr "lista as chaves"
-#: g10/g10.c:172
+#: g10/g10.c:173
msgid "list keys and signatures"
msgstr "lista as chaves e as assinaturas"
-#: g10/g10.c:173
+#: g10/g10.c:174
msgid "check key signatures"
msgstr "confere as assinaturas das chaves"
-#: g10/g10.c:174
+#: g10/g10.c:175
msgid "list keys and fingerprints"
msgstr "lista as chaves e as impressões digitais"
-#: g10/g10.c:175
+#: g10/g10.c:176
msgid "list secret keys"
msgstr "lista as chaves secretas"
-#: g10/g10.c:177
+#: g10/g10.c:178
msgid "generate a new key pair"
msgstr "gera um novo par de chaves"
-#: g10/g10.c:179
+#: g10/g10.c:180
msgid "remove key from the public keyring"
msgstr "remove a chave do anel de chaves público"
-#: g10/g10.c:181
+#: g10/g10.c:182
msgid "sign or edit a key"
msgstr "assina ou edita uma chave"
-#: g10/g10.c:182
+#: g10/g10.c:183
msgid "generate a revocation certificate"
msgstr "gera um certificado de revogação"
-#: g10/g10.c:184
+#: g10/g10.c:185
msgid "export keys"
msgstr "exporta as chaves"
-#: g10/g10.c:187
+#: g10/g10.c:188
msgid "import/merge keys"
msgstr "importa/funde as chaves"
-#: g10/g10.c:189
+#: g10/g10.c:190
msgid "list only the sequence of packets"
msgstr "lista apenas as seqüências de pacotes"
-#: g10/g10.c:192
+#: g10/g10.c:193
msgid "export the ownertrust values"
msgstr "exporta os valores de confiança"
-#: g10/g10.c:194
+#: g10/g10.c:195
msgid "import ownertrust values"
msgstr "importa os valores de confiança"
-#: g10/g10.c:196
+#: g10/g10.c:197
msgid "|[NAMES]|update the trust database"
msgstr "|[NOMES]|atualiza o banco de dados de confiança"
-#: g10/g10.c:198
+#: g10/g10.c:199
msgid "|[NAMES]|check the trust database"
msgstr "|[NOMES]|confere o banco de dados de confiança"
-#: g10/g10.c:199
+#: g10/g10.c:200
msgid "fix a corrupted trust database"
msgstr "conserta um banco de dados de confiança danificado"
-#: g10/g10.c:200
+#: g10/g10.c:201
msgid "De-Armor a file or stdin"
msgstr "Retira a armadura de um arquivo ou \"stdin\""
-#: g10/g10.c:201
+#: g10/g10.c:202
msgid "En-Armor a file or stdin"
msgstr "Cria armadura para um arquivo ou \"stdin\""
-#: g10/g10.c:202
+#: g10/g10.c:203
msgid "|algo [files]|print message digests"
msgstr "|algo [arquivos]|imprime \"digests\" de mensagens"
-#: g10/g10.c:203
+#: g10/g10.c:204
msgid "print all message digests"
msgstr "imprime todos os \"digests\" de mensagens"
-#: g10/g10.c:210
+#: g10/g10.c:211
msgid ""
"@\n"
"Options:\n"
" "
msgstr ""
"@\n"
"Opções:\n"
" "
-#: g10/g10.c:212
+#: g10/g10.c:213
msgid "create ascii armored output"
msgstr "cria uma saída ascii com armadura"
-#: g10/g10.c:214
+#: g10/g10.c:215
msgid "use this user-id to sign or decrypt"
msgstr "usa este identificador de usuário para assinar ou decodificar"
-#: g10/g10.c:215
+#: g10/g10.c:216
msgid "use this user-id for encryption"
msgstr "usa este identificador de usuário para codificar"
-#: g10/g10.c:216
+#: g10/g10.c:217
msgid "|N|set compress level N (0 disables)"
msgstr "|N|estabelece nível de compressão N (0 desabilita)"
-#: g10/g10.c:218
+#: g10/g10.c:219
msgid "use canonical text mode"
msgstr "usa modo de texto canônico"
-#: g10/g10.c:220
+#: g10/g10.c:221
msgid "use as output file"
msgstr "usa como arquivo de saída"
-#: g10/g10.c:221
+#: g10/g10.c:222
msgid "verbose"
msgstr "prolixo"
-#: g10/g10.c:222
+#: g10/g10.c:223
msgid "be somewhat more quiet"
msgstr "ser mais silencioso"
-#: g10/g10.c:223
+#: g10/g10.c:224
msgid "force v3 signatures"
msgstr "força assinaturas v3"
#. { oDryRun, "dry-run", 0, N_("do not make any changes") },
-#: g10/g10.c:225
+#: g10/g10.c:226
msgid "batch mode: never ask"
msgstr "processo de lote: nunca perguntar"
-#: g10/g10.c:226
+#: g10/g10.c:227
msgid "assume yes on most questions"
msgstr "assumir sim para a maioria das perguntas"
-#: g10/g10.c:227
+#: g10/g10.c:228
msgid "assume no on most questions"
msgstr "assumir não para a maioria das perguntas"
-#: g10/g10.c:228
+#: g10/g10.c:229
msgid "add this keyring to the list of keyrings"
msgstr "adiciona este anel de chaves à lista de anéis de chaves"
-#: g10/g10.c:229
+#: g10/g10.c:230
msgid "add this secret keyring to the list"
msgstr "adiciona este anel de chaves secreto à lista"
-#: g10/g10.c:230
+#: g10/g10.c:231
msgid "|NAME|use NAME as default secret key"
msgstr "|NOME|usa NOME como chave secreta padrão"
-#: g10/g10.c:231
+#: g10/g10.c:232
#, fuzzy
msgid "|NAME|set terminal charset to NAME"
msgstr "|NOME| estabelece mapa de caracteres do terminal para NOME"
-#: g10/g10.c:232
+#: g10/g10.c:233
msgid "read options from file"
msgstr "lê opções do arquivo"
-#: g10/g10.c:234
+#: g10/g10.c:235
msgid "set debugging flags"
msgstr "estabelece parâmetros de depuração"
-#: g10/g10.c:235
+#: g10/g10.c:236
msgid "enable full debugging"
msgstr "habilita depuração completa"
-#: g10/g10.c:236
+#: g10/g10.c:237
msgid "|FD|write status info to this FD"
msgstr "|DA|escreve informações de status para este DA"
-#: g10/g10.c:237
+#: g10/g10.c:238
msgid "do not write comment packets"
msgstr "não escreve pacotes de comentário"
-#: g10/g10.c:238
+#: g10/g10.c:239
msgid "(default is 1)"
msgstr "(o padrão é 1)"
-#: g10/g10.c:239
+#: g10/g10.c:240
msgid "(default is 3)"
msgstr "(o padrão é 3)"
-#: g10/g10.c:241
+#: g10/g10.c:242
msgid "|KEYID|ulimately trust this key"
msgstr ""
-#: g10/g10.c:242
+#: g10/g10.c:243
msgid "|FILE|load extension module FILE"
msgstr "|ARQUIVO|carrega módulo de extensão ARQUIVO"
-#: g10/g10.c:243
+#: g10/g10.c:244
msgid "emulate the mode described in RFC1991"
msgstr "emula o modo descrito no RFC1991"
-#: g10/g10.c:244
+#: g10/g10.c:245
msgid "|N|use passphrase mode N"
msgstr "|N|usa frase secreta modo N"
-#: g10/g10.c:246
+#: g10/g10.c:247
msgid "|NAME|use message digest algorithm NAME for passphrases"
msgstr ""
"|NOME|usa algoritmo de \"digest\" de mensagens NOME para\n"
"frases secretas"
-#: g10/g10.c:248
+#: g10/g10.c:249
msgid "|NAME|use cipher algorithm NAME for passphrases"
msgstr ""
"|NOME|usa algoritmo de criptografia NOME para\n"
"frases secretas"
-#: g10/g10.c:250
+#: g10/g10.c:251
msgid "|NAME|use cipher algorithm NAME"
msgstr "|NOME|usa algoritmo de criptografia NOME"
-#: g10/g10.c:251
+#: g10/g10.c:252
msgid "|NAME|use message digest algorithm NAME"
msgstr "|NOME|usa algoritmo de \"digest\" de mensagens NOME"
-#: g10/g10.c:252
+#: g10/g10.c:253
msgid "|N|use compress algorithm N"
msgstr "|N|usa algoritmo de compressão N"
-#: g10/g10.c:253
+#: g10/g10.c:254
msgid "throw keyid field of encrypted packets"
msgstr "elimina o campo keyid dos pacotes codificados"
-#: g10/g10.c:261
+#: g10/g10.c:262
msgid ""
"@\n"
"Examples:\n"
"\n"
" -se -r Bob [file] sign and encrypt for user Bob\n"
" --clearsign [file] make a clear text signature\n"
" --detach-sign [file] make a detached signature\n"
" --list-keys [names] show keys\n"
" --fingerprint [names] show fingerprints\n"
msgstr ""
"@\n"
"Exemplos:\n"
"\n"
" -se -r Bob [arquivo] assina e codifica para usuário Bob\n"
" --clearsign [arquivo] cria uma assinatura em texto puro\n"
" --detach-sign [arquivo] cria uma assinatura separada\n"
" --list-keys [nomes] mostra chaves\n"
" --fingerprint [nomes] mostra impressões digitais\n"
-#: g10/g10.c:339
+#: g10/g10.c:341
msgid "Please report bugs to <gnupg-bugs@gnu.org>.\n"
msgstr "Por favor comunique bugs para <gnupg-bugs@gnu.org>.\n"
-#: g10/g10.c:344
+#: g10/g10.c:346
msgid "Usage: gpgm [options] [files] (-h for help)"
msgstr "Uso: gpgm [opções] [arquivos] (-h para ajuda)"
-#: g10/g10.c:346
+#: g10/g10.c:348
msgid "Usage: gpg [options] [files] (-h for help)"
msgstr "Uso: gpg [opções] [arquivos] (-h para ajuda)"
-#: g10/g10.c:351
+#: g10/g10.c:353
msgid ""
"Syntax: gpgm [options] [files]\n"
"GnuPG maintenance utility\n"
msgstr ""
"Sintaxe: gpgm [opções] [arquivos]\n"
"Utilitário de manutenção do GnuPG\n"
-#: g10/g10.c:354
+#: g10/g10.c:356
msgid ""
"Syntax: gpg [options] [files]\n"
"sign, check, encrypt or decrypt\n"
"default operation depends on the input data\n"
msgstr ""
"Sintaxe: gpg [opções] [arquivos]\n"
"assina, verifica, codifica ou decodifica\n"
"a operação padrão depende dos dados de entrada\n"
-#: g10/g10.c:360
+#: g10/g10.c:362
msgid ""
"\n"
"Supported algorithms:\n"
msgstr ""
"\n"
"Algoritmos suportados:\n"
-#: g10/g10.c:435
+#: g10/g10.c:437
msgid "usage: gpgm [options] "
msgstr "Uso: gpgm [opções] "
-#: g10/g10.c:437
+#: g10/g10.c:439
msgid "usage: gpg [options] "
msgstr "uso: gpg [opções] "
-#: g10/g10.c:478
+#: g10/g10.c:480
msgid "conflicting commands\n"
msgstr "comandos conflitantes\n"
-#: g10/g10.c:616
+#: g10/g10.c:618
#, c-format
msgid "NOTE: no default option file '%s'\n"
msgstr "NOTA: arquivo de opções padrão '%s' inexistente\n"
-#: g10/g10.c:620
+#: g10/g10.c:622
#, c-format
msgid "option file '%s': %s\n"
msgstr "arquivo de opções '%s': %s\n"
-#: g10/g10.c:627
+#: g10/g10.c:629
#, c-format
msgid "reading options from '%s'\n"
msgstr "lendo opções de '%s'\n"
-#: g10/g10.c:776
+#: g10/g10.c:782
#, c-format
msgid "%s is not a valid character set\n"
msgstr "%s não é um mapa de caracteres válido\n"
-#: g10/g10.c:810 g10/g10.c:822
+#: g10/g10.c:817 g10/g10.c:829
msgid "selected cipher algorithm is invalid\n"
msgstr "algoritmo de criptografia selecionado não é válido\n"
-#: g10/g10.c:816 g10/g10.c:828
+#: g10/g10.c:823 g10/g10.c:835
msgid "selected digest algorithm is invalid\n"
msgstr "algoritmo de \"digest\" selecionado não é válido\n"
-#: g10/g10.c:831
+#: g10/g10.c:838
#, c-format
msgid "compress algorithm must be in range %d..%d\n"
msgstr "algoritmo de compressão deve estar na faixa %d..%d\n"
-#: g10/g10.c:833
+#: g10/g10.c:840
msgid "completes-needed must be greater than 0\n"
msgstr "completes-needed deve ser maior que 0\n"
-#: g10/g10.c:835
+#: g10/g10.c:842
msgid "marginals-needed must be greater than 1\n"
msgstr "marginals-needed deve ser maior que 1\n"
-#: g10/g10.c:837
+#: g10/g10.c:844
msgid "max-cert-depth must be in range 1 to 255\n"
msgstr "max-cert-depth deve estar na faixa 1 a 255\n"
-#: g10/g10.c:840
+#: g10/g10.c:847
msgid "NOTE: simple S2K mode (0) is strongly discouraged\n"
msgstr "NOTA: o modo S2K simples (0) não é recomendável\n"
-#: g10/g10.c:844
+#: g10/g10.c:851
msgid "invalid S2K mode; must be 0, 1 or 3\n"
msgstr "modo S2K inválido: deve ser 0, 1 ou 3\n"
-#: g10/g10.c:927
+#: g10/g10.c:934
#, c-format
msgid "failed to initialize the TrustDB: %s\n"
msgstr "falha ao inicializar o banco de dados de confiança: %s\n"
-#: g10/g10.c:933
+#: g10/g10.c:940
msgid "--store [filename]"
msgstr "--store [nome_do_arquivo]"
-#: g10/g10.c:941
+#: g10/g10.c:948
msgid "--symmetric [filename]"
msgstr "--symmetric [nome_do_arquivo]"
-#: g10/g10.c:949
+#: g10/g10.c:956
msgid "--encrypt [filename]"
msgstr "--encrypt [nome_do_arquivo]"
-#: g10/g10.c:962
+#: g10/g10.c:969
msgid "--sign [filename]"
msgstr "--sign [nome_do_arquivo]"
-#: g10/g10.c:975
+#: g10/g10.c:982
msgid "--sign --encrypt [filename]"
msgstr "--sign --encrypt [nome_do_arquivo]"
-#: g10/g10.c:989
+#: g10/g10.c:996
msgid "--clearsign [filename]"
msgstr "--clearsign [nome_do_arquivo]"
-#: g10/g10.c:1001
+#: g10/g10.c:1008
msgid "--decrypt [filename]"
msgstr "--decrypt [nome_do_arquivo]"
-#: g10/g10.c:1010
+#: g10/g10.c:1017
msgid "--edit-key username [commands]"
msgstr "--edit-key nome_do_usuário [comandos]"
-#: g10/g10.c:1026
+#: g10/g10.c:1033
msgid "--delete-secret-key username"
msgstr "--delete-secret-key nome_do_usuário"
-#: g10/g10.c:1029
+#: g10/g10.c:1036
msgid "--delete-key username"
msgstr "--delete-key nome_do_usuário"
-#: g10/encode.c:216 g10/g10.c:1052 g10/sign.c:301
+#: g10/encode.c:216 g10/g10.c:1059 g10/sign.c:301
#, c-format
msgid "can't open %s: %s\n"
msgstr "impossível abrir %s: %s\n"
-#: g10/g10.c:1063
+#: g10/g10.c:1070
msgid "-k[v][v][v][c] [userid] [keyring]"
msgstr "-k[v][v][v][c] [id_do_usuário] [anel_de_chaves]"
-#: g10/g10.c:1120
+#: g10/g10.c:1127
#, c-format
msgid "dearmoring failed: %s\n"
msgstr "retirada de armadura falhou: %s\n"
-#: g10/g10.c:1128
+#: g10/g10.c:1135
#, c-format
msgid "enarmoring failed: %s\n"
msgstr "criação de armadura falhou: %s\n"
-#: g10/g10.c:1194
+#: g10/g10.c:1201
#, c-format
msgid "invalid hash algorithm '%s'\n"
msgstr "algoritmo de distribuição inválido '%s'\n"
-#: g10/g10.c:1273
+#: g10/g10.c:1280
msgid "[filename]"
msgstr "[nome_do_arquivo]"
-#: g10/g10.c:1277
+#: g10/g10.c:1284
msgid "Go ahead and type your message ...\n"
msgstr "Vá em frente e digite sua mensagem ...\n"
-#: g10/decrypt.c:59 g10/g10.c:1280 g10/verify.c:66
+#: g10/decrypt.c:59 g10/g10.c:1287 g10/verify.c:66
#, c-format
msgid "can't open '%s'\n"
msgstr "impossível abrir '%s'\n"
#: g10/armor.c:344 g10/armor.c:391
msgid "armor header: "
msgstr "cabeçalho de armadura: "
#: g10/armor.c:355
msgid "invalid clearsig header\n"
msgstr "cabeçalho de assinatura em texto puro inválido\n"
#: g10/armor.c:382
msgid "invalid armor header: "
msgstr "cabeçalho de armadura inválido: "
#: g10/armor.c:460
#, c-format
msgid "armor: %s\n"
msgstr "armadura: %s\n"
#: g10/armor.c:533
msgid "invalid dash escaped line: "
msgstr "linha com hífen inválida: "
#: g10/armor.c:602
msgid "invalid clear text header: "
msgstr "cabeçalho de texto puro inválido: "
#: g10/armor.c:845
#, c-format
msgid "invalid radix64 character %02x skipped\n"
msgstr "caractere radix64 inválido %02x ignorado\n"
#: g10/armor.c:878
msgid "premature eof (no CRC)\n"
msgstr "fim de arquivo prematuro (sem CRC)\n"
#: g10/armor.c:897
msgid "premature eof (in CRC)\n"
msgstr "fim de arquivo prematuro (no CRC)\n"
#: g10/armor.c:901
msgid "malformed CRC\n"
msgstr "CRC malformado\n"
#: g10/armor.c:905
#, c-format
msgid "CRC error; %06lx - %06lx\n"
msgstr "erro de CRC; %06lx - %06lx\n"
#: g10/armor.c:924
msgid "premature eof (in Trailer)\n"
msgstr "fim de arquivo prematuro (no \"Trailer\")\n"
#: g10/armor.c:928
msgid "error in trailer line\n"
msgstr "erro na linha \"trailer\"\n"
#: g10/armor.c:1182
msgid "no valid RFC1991 or OpenPGP data found.\n"
msgstr "nenum dado RFC1991 ou OpenPGP válido encontrado.\n"
-#: g10/pkclist.c:121
+#: g10/pkclist.c:138
#, c-format
msgid ""
"No trust value assigned to %lu:\n"
"%4u%c/%08lX %s \""
msgstr ""
"Nenhum valor de confiança designado para %lu:\n"
"%4u%c/%08lX %s \""
-#: g10/pkclist.c:131
+#: g10/pkclist.c:148
msgid ""
"Please decide how far you trust this user to correctly\n"
"verify other users' keys (by looking at passports,\n"
"checking fingerprints from different sources...)?\n"
"\n"
" 1 = Don't know\n"
" 2 = I do NOT trust\n"
" 3 = I trust marginally\n"
" 4 = I trust fully\n"
" s = please show me more information\n"
msgstr ""
"Por favor decida quanto você confia neste usuário para\n"
"verificar corretamente as chaves de outros usuários\n"
"(olhando em passaportes, checando impressões digitais\n"
"de outras fontes...)?\n"
"\n"
" 1 = Não sei\n"
" 2 = Eu NÃO confio\n"
" 3 = Eu confio marginalmente\n"
" 4 = Eu confio completamente\n"
" 5 = Mostrar mais informação\n"
-#: g10/pkclist.c:140
+#: g10/pkclist.c:157
msgid " m = back to the main menu\n"
msgstr " m = volta ao menu principal\n"
+#: g10/pkclist.c:159
+msgid " q = quit\n"
+msgstr ""
+
#. a string with valid answers
-#: g10/pkclist.c:145
-msgid "sSmM"
-msgstr "iImM"
+#: g10/pkclist.c:164
+#, fuzzy
+msgid "sSmMqQ"
+msgstr "iImMqQ"
-#: g10/pkclist.c:149
+#: g10/pkclist.c:168
msgid "Your decision? "
msgstr "Sua decisão? "
-#: g10/pkclist.c:169
+#: g10/pkclist.c:188
msgid "Certificates leading to an ultimately trusted key:\n"
msgstr "Certificados que levam a uma chave confiada plenamente:\n"
-#: g10/pkclist.c:197
+#: g10/pkclist.c:221
msgid ""
"Could not find a valid trust path to the key. Let's see whether we\n"
"can assign some missing owner trust values.\n"
"\n"
msgstr ""
"Não foi possível encontrar uma rota de confiança válida para a chave.\n"
"Vamos ver se é possível designar alguns valores de confiança perdidos.\n"
"\n"
-#: g10/pkclist.c:219
+#: g10/pkclist.c:251
msgid ""
"No path leading to one of our keys found.\n"
"\n"
msgstr "Nenhuma rota que leva a uma de nossas chaves encontrada.\n"
-#: g10/pkclist.c:221
+#: g10/pkclist.c:253
msgid ""
"No certificates with undefined trust found.\n"
"\n"
msgstr ""
"Nenhum certificado com confiança indefinida encontrado.\n"
"\n"
-#: g10/pkclist.c:223
+#: g10/pkclist.c:255
msgid ""
"No trust values changed.\n"
"\n"
msgstr ""
"Nenhum valor de confiança modificado.\n"
"\n"
-#: g10/pkclist.c:238
+#: g10/pkclist.c:270
#, c-format
msgid "key %08lX: key has been revoked!\n"
msgstr "chave %08lX: a chave foi revogada!\n"
-#: g10/pkclist.c:244 g10/pkclist.c:335
+#: g10/pkclist.c:276 g10/pkclist.c:369
msgid "Use this key anyway? "
msgstr "Usa esta chave de qualquer modo?"
-#: g10/pkclist.c:266
+#: g10/pkclist.c:298
#, c-format
msgid "%08lX: key has expired\n"
msgstr "%08lX: a chave expirou\n"
-#: g10/pkclist.c:272
+#: g10/pkclist.c:304
#, c-format
msgid "%08lX: no info to calculate a trust probability\n"
msgstr "%08lX: sem informação para calcular probabilidade de confiança\n"
-#: g10/pkclist.c:288
+#: g10/pkclist.c:322
#, c-format
msgid "%08lX: We do NOT trust this key\n"
msgstr "%08lX: Nós NÃO confiamos nesta chave\n"
-#: g10/pkclist.c:294
+#: g10/pkclist.c:328
#, fuzzy, c-format
msgid ""
"%08lX: It is not sure that this key really belongs to the owner\n"
"but it is accepted anyway\n"
msgstr ""
"%08lX: Não se tem certeza de que esta chave realmente pertence ao dono\n"
"mas é aceitada de qualquer modo\n"
-#: g10/pkclist.c:300
+#: g10/pkclist.c:334
msgid "This key probably belongs to the owner\n"
msgstr "Esta chave provavelmente pertence ao dono\n"
-#: g10/pkclist.c:305
+#: g10/pkclist.c:339
msgid "This key belongs to us\n"
msgstr "Esta chave pertence a nós (nós temos a chave secreta)\n"
-#: g10/pkclist.c:330
+#: g10/pkclist.c:364
msgid ""
"It is NOT certain that the key belongs to its owner.\n"
"If you *really* know what you are doing, you may answer\n"
"the next question with yes\n"
"\n"
msgstr ""
"Não se tem certeza de que esta chave pertence a seu dono.\n"
"Se você *realmente* sabe o que está fazendo, pode responder\n"
"afirmativamente à próxima pergunta\n"
"\n"
-#: g10/pkclist.c:339
+#: g10/pkclist.c:373
msgid "WARNING: Using untrusted key!\n"
msgstr "AVISO: Usando chave não confiável!\n"
-#: g10/pkclist.c:375
+#: g10/pkclist.c:409
msgid "WARNING: This key has been revoked by its owner!\n"
msgstr "AVISO: Esta chave foi revogada pelo seu dono!\n"
-#: g10/pkclist.c:376
+#: g10/pkclist.c:410
msgid " This could mean that the signature is forgery.\n"
msgstr " Isto pode significar que a assinatura é falsificada.\n"
-#: g10/pkclist.c:397
+#: g10/pkclist.c:431
msgid "Note: This key has expired!\n"
msgstr "Nota: Esta chave expirou!\n"
-#: g10/pkclist.c:404
+#: g10/pkclist.c:438
msgid "WARNING: This key is not certified with a trusted signature!\n"
msgstr "AVISO: Esta chave não está certificada com uma assinatura confiável!\n"
-#: g10/pkclist.c:406
+#: g10/pkclist.c:440
msgid ""
" There is no indication that the signature belongs to the owner.\n"
msgstr " Não há indicação de que a assinatura pertence ao dono.\n"
-#: g10/pkclist.c:421
+#: g10/pkclist.c:456
msgid "WARNING: We do NOT trust this key!\n"
msgstr "AVISO: Nós NÃO confiamos nesta chave!\n"
-#: g10/pkclist.c:422
+#: g10/pkclist.c:457
msgid " The signature is probably a FORGERY.\n"
msgstr " A assinatura é provavelmente uma FALSIFICAÇÃO.\n"
-#: g10/pkclist.c:429
+#: g10/pkclist.c:464
msgid ""
"WARNING: This key is not certified with sufficiently trusted signatures!\n"
msgstr "AVISO: Esta chave não está certificada com assinaturas confiáveis!\n"
-#: g10/pkclist.c:432
+#: g10/pkclist.c:467
msgid " It is not certain that the signature belongs to the owner.\n"
msgstr " Não se tem certeza de que a assinatura pertence ao dono.\n"
-#: g10/pkclist.c:477
+#: g10/pkclist.c:512
msgid ""
"You did not specify a user ID. (you may use \"-r\")\n"
"\n"
msgstr ""
"Você não especificou um ID de usuário. (pode-se usar \"-r\")\n"
"\n"
-#: g10/pkclist.c:482
+#: g10/pkclist.c:517
msgid "Enter the user ID: "
msgstr "Digite o identificador de usuário:"
-#: g10/pkclist.c:493
+#: g10/pkclist.c:528
msgid "No such user ID.\n"
msgstr "Identificador de usuário inexistente.\n"
-#: g10/pkclist.c:527 g10/pkclist.c:554
+#: g10/pkclist.c:562 g10/pkclist.c:589
#, c-format
msgid "%s: skipped: %s\n"
msgstr "%s: ignorado: %s\n"
-#: g10/pkclist.c:535
+#: g10/pkclist.c:570
#, c-format
msgid "%s: error checking key: %s\n"
msgstr "%s: erro verificando chave: %s\n"
-#: g10/pkclist.c:561
+#: g10/pkclist.c:596
msgid "no valid addressees\n"
msgstr "nenhum endereço válido\n"
#: g10/keygen.c:124
msgid "writing self signature\n"
msgstr "escrevendo auto-assinatura\n"
#: g10/keygen.c:162
msgid "writing key binding signature\n"
msgstr "escrevendo assinatura ligada a uma chave\n"
#: g10/keygen.c:388
msgid "Please select what kind of key you want:\n"
msgstr "Por favor selecione o tipo de chave desejado:\n"
#: g10/keygen.c:390
#, c-format
msgid " (%d) DSA and ElGamal (default)\n"
msgstr " (%d) DSA e ElGamal (padrão)\n"
#: g10/keygen.c:391
#, c-format
msgid " (%d) DSA (sign only)\n"
msgstr " (%d) DSA (apenas assinatura)\n"
#: g10/keygen.c:393
#, c-format
msgid " (%d) ElGamal (encrypt only)\n"
msgstr " (%d) ElGamal (apenas criptografia)\n"
#: g10/keygen.c:394
#, c-format
msgid " (%d) ElGamal (sign and encrypt)\n"
msgstr " (%d) ElGamal (assinatura e criptografia)\n"
#: g10/keygen.c:396
#, c-format
msgid " (%d) ElGamal in a v3 packet\n"
msgstr " (%d) ElGamal em um pacote v3\n"
#: g10/keygen.c:401
msgid "Your selection? "
msgstr "Sua opção? "
#: g10/keygen.c:411
#, fuzzy
msgid "Do you really want to create a sign and encrypt key? "
msgstr "Você realmente quer deletar as chaves selecionadas? "
#: g10/keygen.c:432
msgid "Invalid selection.\n"
msgstr "Opção inválida.\n"
#: g10/keygen.c:444
#, c-format
msgid ""
"About to generate a new %s keypair.\n"
" minimum keysize is 768 bits\n"
" default keysize is 1024 bits\n"
" highest suggested keysize is 2048 bits\n"
msgstr ""
"Prestes a gerar novo par de chaves %s.\n"
" tamanho mínimo é 768 bits\n"
" tamanho padrão é 1024 bits\n"
" tamanho máximo sugerido é 2048 bits\n"
#: g10/keygen.c:451
msgid "What keysize do you want? (1024) "
msgstr "Que tamanho de chave você quer? (1024) "
#: g10/keygen.c:456
msgid "DSA only allows keysizes from 512 to 1024\n"
msgstr "DSA permite apenas tamanhos de 512 a 1024\n"
#: g10/keygen.c:458
msgid "keysize too small; 768 is smallest value allowed.\n"
msgstr "tamanho muito pequeno; 768 é o valor mínimo permitido.\n"
#: g10/keygen.c:461
msgid ""
"Keysizes larger than 2048 are not suggested because\n"
"computations take REALLY long!\n"
msgstr ""
"Tamanhos de chave maiores que 2048 não são recomendados\n"
"porque o tempo de computação é REALMENTE longo!\n"
#: g10/keygen.c:464
msgid "Are you sure that you want this keysize? "
msgstr "Você tem certeza de que quer este tamanho de chave? "
#: g10/keygen.c:465
msgid ""
"Okay, but keep in mind that your monitor and keyboard radiation is also very "
"vulnerable to attacks!\n"
msgstr ""
"Tudo bem, mas tenha em mente que a radiação de seu monitor e teclado também "
"é vulnerável a ataques!\n"
#: g10/keygen.c:473
msgid "Do you really need such a large keysize? "
msgstr "Você realmente precisa de uma chave tão grande? "
#: g10/keygen.c:479
#, c-format
msgid "Requested keysize is %u bits\n"
msgstr "O tamanho de chave pedido é %u bits\n"
#: g10/keygen.c:482 g10/keygen.c:486
#, c-format
msgid "rounded up to %u bits\n"
msgstr "arredondado para %u bits\n"
#: g10/keygen.c:499
msgid ""
"Please specify how long the key should be valid.\n"
" 0 = key does not expire\n"
" <n> = key expires in n days\n"
" <n>w = key expires in n weeks\n"
" <n>m = key expires in n months\n"
" <n>y = key expires in n years\n"
msgstr ""
"Por favor especifique por quanto tempo a chave deve ser válida.\n"
" 0 = chave não expira\n"
" <n> = chave expira em n dias\n"
" <n>w = chave expira em n semanas\n"
" <n>m = chave expira em n meses\n"
" <n>y = chave expira em n anos\n"
#: g10/keygen.c:514
msgid "Key is valid for? (0) "
msgstr "A chave é valida por? (0) "
#: g10/keygen.c:525
msgid "invalid value\n"
msgstr "valor inválido\n"
#: g10/keygen.c:530
msgid "Key does not expire at all\n"
msgstr "A chave não expira nunca\n"
#. print the date when the key expires
#: g10/keygen.c:536
#, c-format
msgid "Key expires at %s\n"
msgstr "A chave expira em %s\n"
#: g10/keygen.c:542
msgid "Is this correct (y/n)? "
msgstr "Está correto (s/n)? "
#: g10/keygen.c:584
msgid ""
"\n"
"You need a User-ID to identify your key; the software constructs the user "
"id\n"
"from Real Name, Comment and Email Address in this form:\n"
" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n"
"\n"
msgstr ""
"\n"
"Você precisa de um identificador de usuário para identificar sua chave; o\n"
"programa constrói o identificador a partir do Nome Completo, Comentário e\n"
"Endereço Eletrônico desta forma:\n"
" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n"
"\n"
#: g10/keygen.c:595
msgid "Real name: "
msgstr "Nome completo: "
#: g10/keygen.c:599
msgid "Invalid character in name\n"
msgstr "Caractere inválido no nome\n"
#: g10/keygen.c:601
msgid "Name may not start with a digit\n"
msgstr "O nome não deve começar com um dígito\n"
#: g10/keygen.c:603
msgid "Name must be at least 5 characters long\n"
msgstr "O nome deve ter pelo menos 5 caracteres\n"
#: g10/keygen.c:611
msgid "Email address: "
msgstr "Endereço de correio eletrônico: "
#: g10/keygen.c:623
msgid "Not a valid email address\n"
msgstr "Endereço eletrônico inválido\n"
#: g10/keygen.c:631
msgid "Comment: "
msgstr "Comentário: "
#: g10/keygen.c:637
msgid "Invalid character in comment\n"
msgstr "Caractere inválido no comentário\n"
#: g10/keygen.c:657
#, c-format
msgid ""
"You selected this USER-ID:\n"
" \"%s\"\n"
"\n"
msgstr ""
"Você selecionou este identificador de usuário:\n"
" \"%s\"\n"
"\n"
#: g10/keygen.c:660
msgid "NnCcEeOoQq"
msgstr "NnCcEeVvSs"
#: g10/keygen.c:670
msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? "
msgstr "Muda (N)ome, (C)omentário, (E)ndereço ou (V)álido/(S)air? "
#: g10/keygen.c:722
msgid ""
"You need a Passphrase to protect your secret key.\n"
"\n"
msgstr ""
"Você precisa de uma frase secreta para proteger sua chave.\n"
"\n"
#: g10/keyedit.c:389 g10/keygen.c:730
msgid "passphrase not correctly repeated; try again.\n"
msgstr "A frase secreta não foi repetida corretamente; tente outra vez.\n"
#: g10/keygen.c:736
msgid ""
"You don't want a passphrase - this is probably a *bad* idea!\n"
"I will do it anyway. You can change your passphrase at any time,\n"
"using this program with the option \"--edit-key\".\n"
"\n"
msgstr ""
"Você não quer uma frase secreta - provavelmente isto é uma *má* idéia!\n"
"Vou fazer isso de qualquer modo. Você pode mudar sua frase secreta a\n"
"qualquer hora, usando este programa com a opção \"--edit-key\".\n"
"\n"
#: g10/keygen.c:757
msgid ""
"We need to generate a lot of random bytes. It is a good idea to perform\n"
"some other action (work in another window, move the mouse, utilize the\n"
"network and the disks) during the prime generation; this gives the random\n"
"number generator a better chance to gain enough entropy.\n"
msgstr ""
"Precisamos gerar muitos bytes aleatórios. É uma boa idéia realizar outra\n"
"atividade (trabalhar em outra janela, mover o mouse, usar a rede e os "
"disco)\n"
"durante a geração dos números primos; isso dá ao gerador de números "
"aleatórios\n"
"uma chance melhor de conseguir entropia suficiente.\n"
#: g10/keygen.c:827
msgid "Key generation can only be used in interactive mode\n"
msgstr "A geração de chaves só pode ser feita em modo interativo\n"
#: g10/keygen.c:835
msgid "DSA keypair will have 1024 bits.\n"
msgstr "O par de chaves DSA terá 1024 bits.\n"
#: g10/keygen.c:841
msgid "Key generation cancelled.\n"
msgstr "Geração de chaves cancelada.\n"
#: g10/keygen.c:851
#, c-format
msgid "writing public certificate to '%s'\n"
msgstr "escrevendo certificado público para '%s'\n"
#: g10/keygen.c:852
#, c-format
msgid "writing secret certificate to '%s'\n"
msgstr "escrevendo certificado privado para '%s'\n"
#: g10/keygen.c:929
msgid "public and secret key created and signed.\n"
msgstr "chaves pública e privada criadas e assinadas.\n"
#: g10/keygen.c:931
msgid ""
"Note that this key cannot be used for encryption. You may want to use\n"
"the command \"--add-key\" to generate a secondary key for this purpose.\n"
msgstr ""
"Note que esta chave não pode ser usada para criptografia. Você pode usar\n"
"o comando \"--add-key\" para gerar uma chave secundária para esse "
"propósito.\n"
#: g10/keygen.c:945 g10/keygen.c:1030
#, c-format
msgid "Key generation failed: %s\n"
msgstr "A geração de chaves falhou: %s\n"
#: g10/keygen.c:1008
msgid "Really create? "
msgstr "Realmente criar? "
#: g10/encode.c:88 g10/openfile.c:81 g10/openfile.c:158 g10/tdbio.c:445
#: g10/tdbio.c:504
#, c-format
msgid "%s: can't open: %s\n"
msgstr "%s: impossível abrir: %s\n"
#: g10/encode.c:107
#, c-format
msgid "error creating passphrase: %s\n"
msgstr "erro criando frase secreta: %s\n"
#: g10/encode.c:155 g10/encode.c:269
#, c-format
msgid "%s: WARNING: empty file\n"
msgstr "%s: AVISO: arquivo vazio\n"
#: g10/encode.c:222
#, c-format
msgid "reading from '%s'\n"
msgstr "lendo de '%s'\n"
#: g10/encode.c:397
#, fuzzy, c-format
msgid "%s/%s encrypted for: %s\n"
msgstr "%s codificado para: %s\n"
#: g10/export.c:114
#, fuzzy, c-format
msgid "%s: user not found: %s\n"
msgstr "%s: usuário não encontrado\n"
#: g10/export.c:123
#, fuzzy, c-format
msgid "certificate read problem: %s\n"
msgstr "erro de leitura do usuário '%s': %s\n"
#: g10/export.c:132
#, fuzzy, c-format
msgid "key %08lX: not a rfc2440 key - skipped\n"
msgstr "chave %08lX: chave secreta sem chave pública - ignorada\n"
#: g10/export.c:174
msgid "WARNING: nothing exported\n"
msgstr "AVISO: nada exportado\n"
#: g10/getkey.c:164
msgid "too many entries in pk cache - disabled\n"
msgstr "entradas demais no cache pk - desabilitado\n"
#: g10/getkey.c:263
msgid "too many entries in unk cache - disabled\n"
msgstr "entradas demais no cache unk - desabilitado\n"
#: g10/getkey.c:989
#, c-format
msgid "using secondary key %08lX instead of primary key %08lX\n"
msgstr "usando chave secundária %08lX ao invés de chave primária %08lX\n"
-#: g10/import.c:129 g10/trustdb.c:1166
+#: g10/import.c:129 g10/trustdb.c:1180
#, c-format
msgid "can't open file: %s\n"
msgstr "impossível abrir arquivo: %s\n"
#: g10/import.c:145
#, c-format
msgid "skipping block of type %d\n"
msgstr "ignorando bloco do tipo %d\n"
-#: g10/import.c:152 g10/trustdb.c:1425 g10/trustdb.c:1494
+#: g10/import.c:152 g10/trustdb.c:1474 g10/trustdb.c:1543
#, c-format
msgid "%lu keys so far processed\n"
msgstr "%lu chaves processadas até agora\n"
-#: g10/import.c:157 g10/trustdb.c:1242
+#: g10/import.c:157 g10/trustdb.c:1256
#, c-format
msgid "read error: %s\n"
msgstr "erro de leitura: %s\n"
#: g10/import.c:159
#, c-format
msgid "Total number processed: %lu\n"
msgstr "Número total processado: %lu\n"
#: g10/import.c:161
#, c-format
msgid " w/o user IDs: %lu\n"
msgstr " sem IDs de usuários: %lu\n"
#: g10/import.c:163
#, c-format
msgid " imported: %lu"
msgstr " importados: %lu"
#: g10/import.c:169
#, c-format
msgid " unchanged: %lu\n"
msgstr " não modificados: %lu\n"
#: g10/import.c:171
#, c-format
msgid " new user IDs: %lu\n"
msgstr " novos IDs de usuários: %lu\n"
#: g10/import.c:173
#, c-format
msgid " new subkeys: %lu\n"
msgstr " novas subchaves: %lu\n"
#: g10/import.c:175
#, c-format
msgid " new signatures: %lu\n"
msgstr " novas assinaturas: %lu\n"
#: g10/import.c:177
#, c-format
msgid " new key revocations: %lu\n"
msgstr " novas revogações de chaves: %lu\n"
#: g10/import.c:179
#, c-format
msgid " secret keys read: %lu\n"
msgstr " chaves secretas lidas: %lu\n"
#: g10/import.c:181
#, c-format
msgid " secret keys imported: %lu\n"
msgstr " chaves secretas importadas: %lu\n"
#: g10/import.c:183
#, c-format
msgid " secret keys unchanged: %lu\n"
msgstr " chaves secretas não modificadas: %lu\n"
#: g10/import.c:325 g10/import.c:517
#, c-format
msgid "key %08lX: no user id\n"
msgstr "chave %08lX: sem id de usuário\n"
#: g10/import.c:336
#, c-format
msgid "key %08lX: no valid user ids\n"
msgstr "chave %08lX: sem ids de usuários válidos\n"
#: g10/import.c:338
msgid "this may be caused by a missing self-signature\n"
msgstr "isto pode ser causado por falta de auto-assinatura\n"
#: g10/import.c:349 g10/import.c:585
#, c-format
msgid "key %08lX: public key not found: %s\n"
msgstr "chave %08lX: chave pública não encontrada: %s\n"
#: g10/import.c:355
msgid "no default public keyring\n"
msgstr "sem anel de chaves público padrão\n"
-#: g10/import.c:359 g10/openfile.c:105 g10/sign.c:205 g10/sign.c:569
+#: g10/import.c:359 g10/openfile.c:105 g10/sign.c:205 g10/sign.c:592
#, c-format
msgid "writing to '%s'\n"
msgstr "escrevendo para '%s'\n"
#: g10/import.c:363 g10/import.c:423 g10/import.c:639
#, c-format
msgid "can't lock public keyring: %s\n"
msgstr "impossível bloquear anel de chaves público: %s\n"
#: g10/import.c:366
#, c-format
msgid "can't write to keyring: %s\n"
msgstr "impossível escrever para o anel de chaves: %s\n"
#: g10/import.c:370
#, c-format
msgid "key %08lX: public key imported\n"
msgstr "chave %08lX: chave pública importada\n"
#: g10/import.c:383
#, c-format
msgid "key %08lX: doesn't match our copy\n"
msgstr "chave %08lX: não corresponde à nossa cópia\n"
#: g10/import.c:396 g10/import.c:594
#, c-format
msgid "key %08lX: can't locate original keyblock: %s\n"
msgstr "chave %08lX: impossível localizar bloco de chaves original: %s\n"
#: g10/import.c:403 g10/import.c:601
#, c-format
msgid "key %08lX: can't read original keyblock: %s\n"
msgstr "chave %08lX: impossível ler bloco de chaves original: %s\n"
#: g10/import.c:420 g10/import.c:532 g10/import.c:636
msgid "writing keyblock\n"
msgstr "escrevendo bloco de chaves\n"
#: g10/import.c:426 g10/import.c:642
#, c-format
msgid "can't write keyblock: %s\n"
msgstr "impossível escrever bloco de chaves: %s\n"
#: g10/import.c:431
#, c-format
msgid "key %08lX: 1 new user-id\n"
msgstr "chave %8lX: 1 novo id de usuário\n"
#: g10/import.c:434
#, c-format
msgid "key %08lX: %d new user-ids\n"
msgstr "chave %08lX: %d novos ids de usuários\n"
#: g10/import.c:437
#, c-format
msgid "key %08lX: 1 new signature\n"
msgstr "chave %08lX: 1 nova assinatura\n"
#: g10/import.c:440
#, c-format
msgid "key %08lX: %d new signatures\n"
msgstr "chave %08lX: %d novas assinaturas\n"
#: g10/import.c:443
#, c-format
msgid "key %08lX: 1 new subkey\n"
msgstr "chave %08lX: 1 nova subchave\n"
#: g10/import.c:446
#, c-format
msgid "key %08lX: %d new subkeys\n"
msgstr "chave %08lX: %d novas subchaves\n"
#: g10/import.c:456
#, c-format
msgid "key %08lX: not changed\n"
msgstr "chave %08lX: não modificada\n"
#: g10/import.c:535
#, c-format
msgid "can't lock secret keyring: %s\n"
msgstr "impossível bloquear anel de chaves secreto: %s\n"
#: g10/import.c:538
#, c-format
msgid "can't write keyring: %s\n"
msgstr "impossível escrever anel de chaves: %s\n"
#. we are ready
#: g10/import.c:541
#, c-format
msgid "key %08lX: secret key imported\n"
msgstr "chave %08lX: chave secreta importada\n"
#. we can't merge secret keys
#: g10/import.c:545
#, c-format
msgid "key %08lX: already in secret keyring\n"
msgstr "chave %08lX: já no anel de chaves secreto\n"
#: g10/import.c:550
#, c-format
msgid "key %08lX: secret key not found: %s\n"
msgstr "chave %08lX: chave secreta não encontrada: %s\n"
#: g10/import.c:579
#, c-format
msgid "key %08lX: no public key - can't apply revocation certificate\n"
msgstr ""
"chave %08lX: sem chave pública - impossível aplicar certificado\n"
"de revogação\n"
#: g10/import.c:612
#, c-format
msgid "key %08lX: invalid revocation certificate: %s - rejected\n"
msgstr "chave %08lX: certificado de revogação inválido: %s - rejeitado\n"
#: g10/import.c:646
#, c-format
msgid "key %08lX: revocation certificate imported\n"
msgstr "chave %08lX: certificado de revogação importado\n"
#: g10/import.c:677
#, c-format
msgid "key %08lX: no user-id for signature\n"
msgstr "chave %08lX: sem id de usuário para assinatura\n"
#: g10/import.c:684
#, c-format
msgid "key %08lX: unsupported public key algorithm\n"
msgstr "chave %08lX: algoritmo de chave pública não suportado\n"
#: g10/import.c:685
#, c-format
msgid "key %08lX: invalid self-signature\n"
msgstr "chave %08lX: auto-assinatura inválida\n"
#: g10/import.c:714
#, c-format
msgid "key %08lX: skipped userid '"
msgstr "chave %08lX: id de usuário ignorado '"
#: g10/import.c:737
#, c-format
msgid "key %08lX: revocation certificate at wrong place - skipped\n"
msgstr "chave %08lX: certificado de revogação no local errado - ignorado\n"
#: g10/import.c:745
#, c-format
msgid "key %08lX: invalid revocation certificate: %s - skipped\n"
msgstr "chave %08lX: certificado de revogação inválido: %s - ignorado\n"
#: g10/import.c:804
#, c-format
msgid "key %08lX: revocation certificate added\n"
msgstr "chave %08lX: certificado de revogação adicionado\n"
#: g10/import.c:918 g10/import.c:973
#, c-format
msgid "key %08lX: our copy has no self-signature\n"
msgstr "chave %08lX: nossa cópia não tem auto-assinatura\n"
#: g10/keyedit.c:81
#, c-format
msgid "%s: user not found\n"
msgstr "%s: usuário não encontrado\n"
#: g10/keyedit.c:164
msgid "[self-signature]"
msgstr "[auto-assinatura]"
#: g10/keyedit.c:182
msgid "1 bad signature\n"
msgstr "1 assinatura incorreta\n"
#: g10/keyedit.c:184
#, c-format
msgid "%d bad signatures\n"
msgstr "%d assinaturas incorretas\n"
#: g10/keyedit.c:186
msgid "1 signature not checked due to a missing key\n"
msgstr "1 assinatura não verificada por falta de chave\n"
#: g10/keyedit.c:188
#, c-format
msgid "%d signatures not checked due to missing keys\n"
msgstr "%d assinaturas não verificadas por falta de chaves\n"
#: g10/keyedit.c:190
msgid "1 signature not checked due to an error\n"
msgstr "1 assinatura não checada por causa de um erro\n"
#: g10/keyedit.c:192
#, c-format
msgid "%d signatures not checked due to errors\n"
msgstr "%d assinaturas não verificadas por causa de erros\n"
#: g10/keyedit.c:194
msgid "1 user id without valid self-signature detected\n"
msgstr "1 id de usuário sem auto-assinatura válida detectado\n"
#: g10/keyedit.c:196
#, c-format
msgid "%d user ids without valid self-signatures detected\n"
msgstr "%d ids de usuários sem auto-assinaturas válidas detectados\n"
#: g10/keyedit.c:258
#, c-format
msgid "Already signed by key %08lX\n"
msgstr "Já assinado pela chave %08lX\n"
#: g10/keyedit.c:266
#, c-format
msgid "Nothing to sign with key %08lX\n"
msgstr "Nada para assinar com a chave %08lX\n"
#: g10/keyedit.c:275
msgid ""
"Are you really sure that you want to sign this key\n"
"with your key: \""
msgstr ""
"Você tem certeza de que quer assinar esta chave com\n"
"sua chave: \""
#: g10/keyedit.c:282
msgid "Really sign? "
msgstr "Realmente assinar? "
#: g10/keyedit.c:303 g10/sign.c:65
#, c-format
msgid "signing failed: %s\n"
msgstr "assinatura falhou: %s\n"
#: g10/keyedit.c:356
msgid "This key is not protected.\n"
msgstr "Esta chave não é protegida.\n"
#: g10/keyedit.c:359
msgid "Key is protected.\n"
msgstr "A chave é protegida.\n"
#: g10/keyedit.c:376
#, c-format
msgid "Can't edit this key: %s\n"
msgstr "Impossível editar esta chave: %s\n"
#: g10/keyedit.c:381
msgid ""
"Enter the new passphrase for this secret key.\n"
"\n"
msgstr ""
"Digite a nova frase para esta chave secreta.\n"
"\n"
#: g10/keyedit.c:393
msgid ""
"You don't want a passphrase - this is probably a *bad* idea!\n"
"\n"
msgstr ""
"Você não quer uma frase secreta - provavelmente isto é uma *má* idéia!\n"
"\n"
#: g10/keyedit.c:396
msgid "Do you really want to do this? "
msgstr "Você realmente quer fazer isso? "
#: g10/keyedit.c:455
msgid "moving a key signature to the correct place\n"
msgstr "movendo a assinatura da chave para o local correto\n"
#: g10/keyedit.c:490
msgid "quit"
msgstr "sair"
#: g10/keyedit.c:490
msgid "quit this menu"
msgstr "sair deste menu"
#: g10/keyedit.c:491
msgid "q"
msgstr "s"
#: g10/keyedit.c:492
msgid "save"
msgstr "gravar"
#: g10/keyedit.c:492
msgid "save and quit"
msgstr "gravar e sair"
#: g10/keyedit.c:493
msgid "help"
msgstr "ajuda"
#: g10/keyedit.c:493
msgid "show this help"
msgstr "mostra esta ajuda"
#: g10/keyedit.c:495
msgid "fpr"
msgstr ""
#: g10/keyedit.c:495
msgid "show fingerprint"
msgstr "mostra impressão digital"
#: g10/keyedit.c:496
msgid "list"
msgstr "lista"
#: g10/keyedit.c:496
msgid "list key and user ids"
msgstr "lista chave e identificadores de usuários"
#: g10/keyedit.c:497
msgid "l"
msgstr ""
#: g10/keyedit.c:498
msgid "uid"
msgstr ""
#: g10/keyedit.c:498
msgid "select user id N"
msgstr "seleciona id de usuário N"
#: g10/keyedit.c:499
msgid "key"
msgstr "chave"
#: g10/keyedit.c:499
msgid "select secondary key N"
msgstr "seleciona chave secundária N"
#: g10/keyedit.c:500
msgid "check"
msgstr "verifica"
#: g10/keyedit.c:500
msgid "list signatures"
msgstr "lista assinaturas"
#: g10/keyedit.c:501
msgid "c"
msgstr "v"
#: g10/keyedit.c:502
msgid "sign"
msgstr "assina"
#: g10/keyedit.c:502
msgid "sign the key"
msgstr "assina a chave"
#: g10/keyedit.c:503
msgid "s"
msgstr "a"
#: g10/keyedit.c:504
msgid "debug"
msgstr "depura"
#: g10/keyedit.c:505
msgid "adduid"
msgstr ""
#: g10/keyedit.c:505
msgid "add a user id"
msgstr "adiciona um novo id de usuário"
#: g10/keyedit.c:506
msgid "deluid"
msgstr ""
#: g10/keyedit.c:506
msgid "delete user id"
msgstr "deleta id de usuário"
#: g10/keyedit.c:507
msgid "addkey"
msgstr ""
#: g10/keyedit.c:507
msgid "add a secondary key"
msgstr "adiciona nova chave secundária"
#: g10/keyedit.c:508
msgid "delkey"
msgstr ""
#: g10/keyedit.c:508
msgid "delete a secondary key"
msgstr "deleta uma chave secundária"
#: g10/keyedit.c:509
msgid "expire"
msgstr "expira"
#: g10/keyedit.c:509
msgid "change the expire date"
msgstr "muda a data em que a chave expira"
#: g10/keyedit.c:510
msgid "toggle"
msgstr "comuta"
#: g10/keyedit.c:510
msgid "toggle between secret and public key listing"
msgstr "comuta entre listagem de chave secreta e pública"
#: g10/keyedit.c:512
msgid "t"
msgstr "c"
#: g10/keyedit.c:513
msgid "pref"
msgstr ""
#: g10/keyedit.c:513
msgid "list preferences"
msgstr "lista preferências"
#: g10/keyedit.c:514
msgid "passwd"
msgstr "senha"
#: g10/keyedit.c:514
msgid "change the passphrase"
msgstr "muda a frase secreta"
#: g10/keyedit.c:515
msgid "trust"
msgstr "confianca"
#: g10/keyedit.c:515
msgid "change the ownertrust"
msgstr "muda os valores de confiança"
#: g10/keyedit.c:534
msgid "can't do that in batchmode\n"
msgstr "impossível fazer isso em modo de processo por lotes\n"
#. check that they match
#. FIXME: check that they both match
#: g10/keyedit.c:561
msgid "Secret key is available.\n"
msgstr "Chave secreta disponível\n"
#: g10/keyedit.c:590
msgid "Command> "
msgstr "Comando> "
#: g10/keyedit.c:617
#, fuzzy
msgid "Need the secret key to do this.\n"
msgstr "A chave secreta é necessária para fazer isto.\n"
#: g10/keyedit.c:639
msgid "Save changes? "
msgstr "Salvar alterações? "
#: g10/keyedit.c:642
msgid "Quit without saving? "
msgstr "Sair sem salvar? "
#: g10/keyedit.c:652
#, c-format
msgid "update failed: %s\n"
msgstr "atualização falhou: %s\n"
#: g10/keyedit.c:659
#, c-format
msgid "update secret failed: %s\n"
msgstr "atualização da chave secreta falhou: %s\n"
#: g10/keyedit.c:666
msgid "Key not changed so no update needed.\n"
msgstr "Chave sem mudanças, nenhuma atualização é necessária.\n"
#: g10/keyedit.c:669 g10/keyedit.c:727
#, c-format
msgid "update of trust db failed: %s\n"
msgstr "atualização da confiança falhou: %s\n"
#: g10/keyedit.c:701
msgid "Really sign all user ids? "
msgstr "Realmente assinar todos os ids de usuário? "
#: g10/keyedit.c:702
msgid "Hint: Select the user ids to sign\n"
msgstr "Sugestão: Selecione os ids de usuário para assinar\n"
#: g10/keyedit.c:738
msgid "You must select at least one user id.\n"
msgstr "Você precisa selecionar pelo menos um id de usuário.\n"
#: g10/keyedit.c:740
msgid "You can't delete the last user id!\n"
msgstr "Você não pode deletar o último id de usuário!\n"
#: g10/keyedit.c:743
msgid "Really remove all selected user ids? "
msgstr "Realmente remover todos os ids de usuário selecionados? "
#: g10/keyedit.c:744
msgid "Really remove this user id? "
msgstr "Realmente remover este id de usuário? "
#: g10/keyedit.c:767
msgid "You must select at least one key.\n"
msgstr "Você deve selecionar pelo menos uma chave.\n"
#: g10/keyedit.c:771
msgid "Do you really want to delete the selected keys? "
msgstr "Você realmente quer deletar as chaves selecionadas? "
#: g10/keyedit.c:772
msgid "Do you really want to delete this key? "
msgstr "Você realmente quer deletar esta chave? "
#: g10/keyedit.c:819
msgid "Invalid command (try \"help\")\n"
msgstr "Comando inválido (tente \"ajuda\")\n"
#: g10/keyedit.c:1197
msgid "Please remove selections from the secret keys.\n"
msgstr "Por favor remova as seleções das chaves secretas.\n"
#: g10/keyedit.c:1203
msgid "Please select at most one secondary key.\n"
msgstr "Por favor selecione no máximo uma chave secundária.\n"
#: g10/keyedit.c:1207
msgid "Changing exiration time for a secondary key.\n"
msgstr "Modificando data de expiração para a chave secundária.\n"
#: g10/keyedit.c:1209
msgid "Changing exiration time for the primary key.\n"
msgstr "Modificando data de expiração para a chave primária.\n"
#: g10/keyedit.c:1250
msgid "You can't change the expiration date of a v3 key\n"
msgstr "Você não pode modificar a data de expiração de uma chave v3\n"
#: g10/keyedit.c:1266
msgid "No corresponding signature in secret ring\n"
msgstr "Nenhuma assinatura correspondente no anel de chaves secreto\n"
#: g10/keyedit.c:1326
#, c-format
msgid "No user id with index %d\n"
msgstr "Nenhum id de usuário com índice %d\n"
#: g10/keyedit.c:1371
#, c-format
msgid "No secondary key with index %d\n"
msgstr "Nenhuma chave secundária com índice %d\n"
#: g10/mainproc.c:198
#, fuzzy
msgid "public key encrypted data: Good DEK\n"
msgstr "dados codificados com chave pública: DEK bom\n"
#: g10/mainproc.c:201
#, c-format
msgid "public key decryption failed: %s\n"
msgstr "decodificação de chave pública falhou: %s\n"
#: g10/mainproc.c:228
msgid "decryption okay\n"
msgstr "decodificação correta\n"
#: g10/mainproc.c:231
#, c-format
msgid "decryption failed: %s\n"
msgstr "decodifiação falhou: %s\n"
#: g10/mainproc.c:248
msgid "NOTE: sender requested \"for-your-eyes-only\"\n"
msgstr "NOTA: o remetente solicitou \"apenas-para-seus-olhos\"\n"
#: g10/mainproc.c:250
#, c-format
msgid "original file name='%.*s'\n"
msgstr "nome de arquivo original='%.*s'\n"
#: g10/mainproc.c:833
msgid "signature verification suppressed\n"
msgstr "verifiação de assinatura suprimida\n"
#: g10/mainproc.c:839
#, c-format
msgid "Signature made %.*s using %s key ID %08lX\n"
msgstr "Assinatura feita %.*s usando %s ID da chave %08lX\n"
#: g10/mainproc.c:847
msgid "BAD signature from \""
msgstr "Assinatura INCORRETA de \""
#: g10/mainproc.c:848
msgid "Good signature from \""
msgstr "Assinatura correta de\""
#: g10/mainproc.c:861
#, c-format
msgid "Can't check signature: %s\n"
msgstr "Impossível verificar assinatura: %s\n"
#: g10/mainproc.c:934
msgid "old style (PGP 2.x) signature\n"
msgstr "assinatura antiga (PGP2.x)\n"
#: g10/mainproc.c:939
msgid "invalid root packet detected in proc_tree()\n"
msgstr "pacote raiz inválido detectado em proc_tree()\n"
#: g10/misc.c:88
#, c-format
msgid "can't disable core dumps: %s\n"
msgstr "impossível desabilitar core dumps: %s\n"
#: g10/misc.c:90
msgid "WARNING: Program may create a core file!\n"
msgstr "AVISO: O programa pode criar um arquivo core!\n"
#: g10/misc.c:198
msgid "Experimental algorithms should not be used!\n"
msgstr ""
#: g10/misc.c:212
msgid ""
"RSA keys are deprecated; please consider creating a new key and use this key "
"in the future\n"
msgstr ""
"Chaves RSA não são recomendáveis; por favor considere criar uma nova chave e "
"usá-la no futuro\n"
#: g10/misc.c:233
msgid "This cipher algorithm is depreciated; please use a more standard one!\n"
msgstr ""
#: g10/parse-packet.c:109
#, c-format
msgid "can't handle public key algorithm %d\n"
msgstr "impossível manipular algoritmo de chave pública %d\n"
+#: g10/parse-packet.c:801
+#, c-format
+msgid "subpacket of type %d has critical bit set\n"
+msgstr ""
+
#: g10/passphrase.c:141
msgid ""
"\n"
"You need a passphrase to unlock the secret key for\n"
"user: \""
msgstr ""
"\n"
"Você precisa de uma frase para desbloquear a chave secreta do\n"
"usuário: \""
#: g10/passphrase.c:150
#, c-format
msgid "(%u-bit %s key, ID %08lX, created %s)\n"
msgstr "(chave %u-bit/%s, ID %08lX, criada em %s)\n"
#: g10/passphrase.c:174
msgid "Enter passphrase: "
msgstr "Digite a frase secreta: "
#: g10/passphrase.c:178
msgid "Repeat passphrase: "
msgstr "Repita a frase secreta: "
-#: g10/plaintext.c:102
+#: g10/plaintext.c:103
msgid "data not saved; use option \"--output\" to save it\n"
msgstr "dados não salvos; use a opção \"--output\" para salvá-los\n"
-#: g10/plaintext.c:215
+#: g10/plaintext.c:216
msgid "Please enter name of data file: "
msgstr "Por favor digite o nome do arquivo de dados: "
-#: g10/plaintext.c:236
+#: g10/plaintext.c:237
msgid "reading stdin ...\n"
msgstr "lendo \"stdin\" ...\n"
-#: g10/plaintext.c:299
+#: g10/plaintext.c:300
#, c-format
msgid "can't open signed data '%s'\n"
msgstr "impossível abrir dados assinados '%s'\n"
#: g10/pubkey-enc.c:78
#, c-format
msgid "anonymous receiver; trying secret key %08lX ...\n"
msgstr "destinatário anônimo; tentando chave secreta %08lX ...\n"
#: g10/pubkey-enc.c:84
msgid "okay, we are the anonymous receiver.\n"
msgstr "correto, nós somos o destinatário anônimo.\n"
#: g10/pubkey-enc.c:136
msgid "old encoding of the DEK is not supported\n"
msgstr "codificação antiga do DEK não suportada\n"
#: g10/pubkey-enc.c:183
#, c-format
msgid "NOTE: cipher algorithm %d not found in preferences\n"
msgstr "NOTA: algoritmo de criptografia %d não encontrado nas preferências\n"
#: g10/seckey-cert.c:56
#, c-format
msgid "protection algorithm %d is not supported\n"
msgstr "algoritmo de proteção %d não é suportado\n"
#: g10/seckey-cert.c:169
msgid "Invalid passphrase; please try again ...\n"
msgstr "Frase secreta inválida; por favor tente novamente ...\n"
#: g10/seckey-cert.c:216
msgid "WARNING: Weak key detected - please change passphrase again.\n"
msgstr ""
"AVISO: Chave fraca detectada - por favor mude a frase secreta novamente\n"
#: g10/sig-check.c:155
msgid ""
"this is a PGP generated ElGamal key which is NOT secure for signatures!\n"
msgstr ""
"esta é uma chave ElGamal gerada pelo PGP que NÃO é segura para assinaturas!\n"
#: g10/sig-check.c:165
msgid "public key created in future (time warp or clock problem)\n"
msgstr ""
"chave pública criada no futuro (viagem no tempo ou problema no relógio)\n"
#: g10/sig-check.c:170
#, c-format
msgid "NOTE: signature key expired %s\n"
msgstr "NOTA: chave de assinatura expirou %s\n"
+#: g10/sig-check.c:226
+msgid "assuming bad signature due to an unknown critical bit\n"
+msgstr ""
+
#: g10/sign.c:69
#, c-format
msgid "%s signature from: %s\n"
msgstr "%s assinatura de: %s\n"
-#: g10/sign.c:200 g10/sign.c:564
+#: g10/sign.c:200 g10/sign.c:587
#, c-format
msgid "can't create %s: %s\n"
msgstr "impossível criar %s: %s\n"
#: g10/sign.c:296
msgid "signing:"
msgstr "assinando:"
#: g10/sign.c:336
#, c-format
msgid "WARNING: '%s' is an empty file\n"
msgstr "AVISO: '%s' é um arquivo vazio\n"
#: g10/tdbio.c:116 g10/tdbio.c:1413
#, fuzzy, c-format
msgid "trustdb rec %lu: lseek failed: %s\n"
msgstr "banco de dados de confiança rec %lu: lseek falhou: %s\n"
#: g10/tdbio.c:122 g10/tdbio.c:1420
#, fuzzy, c-format
msgid "trustdb rec %lu: write failed (n=%d): %s\n"
msgstr "banco de dados de confiança rec %lu: escrita falhou (n=%d): %s\n"
#: g10/tdbio.c:232
msgid "trustdb transaction to large\n"
msgstr "transação de banco de dados de confiança muito grande\n"
#: g10/tdbio.c:402
#, c-format
msgid "%s: can't access: %s\n"
msgstr "%s: impossível acessar: %s\n"
#: g10/ringedit.c:273 g10/tdbio.c:422
#, c-format
msgid "%s: can't create directory: %s\n"
msgstr "%s: impossível criar diretório: %s\n"
#: g10/ringedit.c:279 g10/tdbio.c:425
#, c-format
msgid "%s: directory created\n"
msgstr "%s: diretório criado\n"
#: g10/tdbio.c:429
#, c-format
msgid "%s: directory does not exist!\n"
msgstr "%s: diretório inexistente!\n"
#: g10/openfile.c:101 g10/openfile.c:165 g10/ringedit.c:1256 g10/tdbio.c:435
#, c-format
msgid "%s: can't create: %s\n"
msgstr "%s: impossível criar: %s\n"
#: g10/tdbio.c:459
#, c-format
msgid "%s: failed to create version record: %s"
msgstr "%s: falha ao criar registro de versão: %s"
#: g10/tdbio.c:463
#, c-format
msgid "%s: invalid trust-db created\n"
msgstr "%s: banco de dados de confiança inválido criado\n"
#: g10/tdbio.c:465
#, c-format
msgid "%s: trust-db created\n"
msgstr "%s: banco de dados de confiança criado\n"
#: g10/tdbio.c:506
#, c-format
msgid "%s: invalid trust-db\n"
msgstr "%s: banco de dados de confiança inválido\n"
#: g10/tdbio.c:540
#, c-format
msgid "%s: failed to create hashtable: %s\n"
msgstr "%s: falha ao criar tabela \"hash\": %s\n"
#: g10/tdbio.c:548
#, c-format
msgid "%s: error updating version record: %s\n"
msgstr "%s: erro atualizando registro de versão: %s\n"
#: g10/tdbio.c:564 g10/tdbio.c:603 g10/tdbio.c:628 g10/tdbio.c:1346
#: g10/tdbio.c:1373
#, c-format
msgid "%s: error reading version record: %s\n"
msgstr "%s: erro lendo registro de versão: %s\n"
#: g10/tdbio.c:577
#, c-format
msgid "%s: error writing version record: %s\n"
msgstr "%s: erro escrevendo registro de versão: %s\n"
#: g10/tdbio.c:1053
#, c-format
msgid "trustdb: lseek failed: %s\n"
msgstr "banco de dados de confiança: lseek falhou: %s\n"
#: g10/tdbio.c:1061
#, c-format
msgid "trustdb: read failed (n=%d): %s\n"
msgstr "banco de dados de confiança: leitura falhou (n=%d): %s\n"
#: g10/tdbio.c:1082
#, c-format
msgid "%s: not a trustdb file\n"
msgstr "%s: não é um banco de dados de confiança\n"
#: g10/tdbio.c:1098
#, c-format
msgid "%s: version record with recnum %lu\n"
msgstr "%s: registro de versão com recnum %lu\n"
#: g10/tdbio.c:1103
#, c-format
msgid "%s: invalid file version %d\n"
msgstr "%s: versão de arquivo inválida %d\n"
#: g10/tdbio.c:1379
#, c-format
msgid "%s: error reading free record: %s\n"
msgstr "%s: erro lendo registro livre: %s\n"
#: g10/tdbio.c:1387
#, fuzzy, c-format
msgid "%s: error writing dir record: %s\n"
msgstr "%s: erro escrevendo registro de diretório: %s\n"
#: g10/tdbio.c:1397
#, c-format
msgid "%s: failed to zero a record: %s\n"
msgstr "%s: falha ao zerar um registro: %s\n"
#: g10/tdbio.c:1427
#, c-format
msgid "%s: failed to append a record: %s\n"
msgstr "%s: falha ao anexar um registro: %s\n"
-#: g10/trustdb.c:134
+#: g10/trustdb.c:142
msgid "The trust DB is corrupted; please run \"gpgm --fix-trust-db\".\n"
msgstr ""
"O banco de dados de confiança está danificado; por favor rode\n"
"\"gpgm --fix-trust-db\".\n"
-#: g10/trustdb.c:147
+#: g10/trustdb.c:155
#, fuzzy, c-format
msgid "trust record %lu, req type %d: read failed: %s\n"
msgstr "registro de confiança %lu, tipo req %d: leitura falhou: %s\n"
-#: g10/trustdb.c:162
+#: g10/trustdb.c:170
#, c-format
msgid "trust record %lu, type %d: write failed: %s\n"
msgstr "registro de confiança %lu, tipo %d: gravação falhou: %s\n"
-#: g10/trustdb.c:176
+#: g10/trustdb.c:184
#, c-format
msgid "trust record %lu: delete failed: %s\n"
msgstr "registro de confiança %lu: remoção falhou: %s\n"
-#: g10/trustdb.c:190
+#: g10/trustdb.c:198
#, c-format
msgid "trust db: sync failed: %s\n"
msgstr "banco de dados de confiança: sincronização falhou: %s\n"
-#: g10/trustdb.c:319
+#: g10/trustdb.c:327
#, fuzzy, c-format
msgid "error reading dir record for LID %lu: %s\n"
msgstr "erro lendo registro de diretório para LID %lu: %s\n"
-#: g10/trustdb.c:326
+#: g10/trustdb.c:334
#, fuzzy, c-format
msgid "lid %lu: expected dir record, got type %d\n"
msgstr "lid %lu: registro de diretório esperado, tipo %d recebido\n"
-#: g10/trustdb.c:331
+#: g10/trustdb.c:339
#, c-format
msgid "no primary key for LID %lu\n"
msgstr "nenhuma chave primária para LID %lu\n"
-#: g10/trustdb.c:336
+#: g10/trustdb.c:344
#, c-format
msgid "error reading primary key for LID %lu: %s\n"
msgstr "erro lendo chave primária para LID %lu: %s\n"
-#: g10/trustdb.c:412
+#: g10/trustdb.c:420
#, fuzzy, c-format
msgid "chained sigrec %lu has a wrong owner\n"
msgstr "sigrec em cadeia %lu possui dono errado\n"
-#: g10/trustdb.c:455
+#: g10/trustdb.c:463
#, fuzzy, c-format
msgid "'%s' is not a valid long keyID\n"
msgstr "%s não é um mapa de caracteres válido\n"
-#: g10/trustdb.c:490
+#: g10/trustdb.c:498
#, fuzzy, c-format
msgid "key %08lX: no public key for trusted key - skipped\n"
msgstr "chave %08lX: chave secreta sem chave pública - ignorada\n"
-#: g10/trustdb.c:499 g10/trustdb.c:557
+#: g10/trustdb.c:507 g10/trustdb.c:565
#, c-format
msgid "key %08lX: can't put it into the trustdb\n"
msgstr "chave %08lX: impossível colocá-la no banco de dados de confiança\n"
-#: g10/trustdb.c:504 g10/trustdb.c:563
+#: g10/trustdb.c:512 g10/trustdb.c:571
#, c-format
msgid "key %08lX: query record failed\n"
msgstr "chave %08lX: pedido de registro falhou\n"
-#: g10/trustdb.c:509 g10/trustdb.c:572
+#: g10/trustdb.c:517 g10/trustdb.c:580
#, fuzzy, c-format
msgid "key %08lX: already in trusted key table\n"
msgstr "chave %08lX: já está na tabela de chaves secretas\n"
-#: g10/trustdb.c:512 g10/trustdb.c:575
+#: g10/trustdb.c:520 g10/trustdb.c:583
#, fuzzy, c-format
msgid "key %08lX: accepted as trusted key.\n"
msgstr "chave %08lX: aceita como chave secreta.\n"
-#: g10/trustdb.c:528
+#: g10/trustdb.c:536
#, c-format
msgid "NOTE: secret key %08lX is NOT protected.\n"
msgstr "NOTA: chave secreta %08lX NÃO está protegida.\n"
-#: g10/trustdb.c:540
+#: g10/trustdb.c:548
#, c-format
msgid "key %08lX: secret key without public key - skipped\n"
msgstr "chave %08lX: chave secreta sem chave pública - ignorada\n"
-#: g10/trustdb.c:547
+#: g10/trustdb.c:555
#, c-format
msgid "key %08lX: secret and public key don't match\n"
msgstr "chave %08lX: chaves secreta e pública não combinam\n"
-#: g10/trustdb.c:583
+#: g10/trustdb.c:591
#, c-format
msgid "enumerate secret keys failed: %s\n"
msgstr "enumeração de chaves secretas falhou: %s\n"
-#: g10/trustdb.c:766
+#: g10/trustdb.c:774
#, fuzzy, c-format
msgid "lid %lu: read dir record failed: %s\n"
msgstr "lid %lu: leitura de registro de diretório falhou: %s\n"
-#: g10/trustdb.c:775
+#: g10/trustdb.c:783
#, c-format
msgid "lid %lu: read key record failed: %s\n"
msgstr "lid %lu: leitura de registro de chave falhou: %s\n"
-#: g10/trustdb.c:785
+#: g10/trustdb.c:793
#, c-format
msgid "lid %lu: read uid record failed: %s\n"
msgstr "lid %lu: leitura de registro de uid falhou: %s\n"
-#: g10/trustdb.c:794
+#: g10/trustdb.c:802
#, fuzzy, c-format
msgid "lid %lu: read pref record failed: %s\n"
msgstr "lid %lu: leitura de registro de preferências falhou: %s\n"
-#: g10/trustdb.c:804
+#: g10/trustdb.c:812
#, c-format
msgid "lid %lu: read sig record failed: %s\n"
msgstr "lid %lu: leitura de registro de assinatura falhou: %s\n"
-#: g10/trustdb.c:999
+#: g10/trustdb.c:1013
msgid "Ooops, no keys\n"
msgstr "Ooops, nenhuma chave\n"
-#: g10/trustdb.c:1003
+#: g10/trustdb.c:1017
msgid "Ooops, no user ids\n"
msgstr "Ooops, nenhum id de usuário\n"
-#: g10/trustdb.c:1074 g10/trustdb.c:1092
+#: g10/trustdb.c:1088 g10/trustdb.c:1106
#, c-format
msgid "user '%s' read problem: %s\n"
msgstr "erro de leitura do usuário '%s': %s\n"
-#: g10/trustdb.c:1077 g10/trustdb.c:1095
+#: g10/trustdb.c:1091 g10/trustdb.c:1109
#, c-format
msgid "user '%s' list problem: %s\n"
msgstr "erro de listagem do usuário '%s': %s\n"
-#: g10/trustdb.c:1085 g10/trustdb.c:1300
+#: g10/trustdb.c:1099 g10/trustdb.c:1346
#, c-format
msgid "user '%s' not found: %s\n"
msgstr "usuário '%s' não encontrado: %s\n"
-#: g10/trustdb.c:1087 g10/trustdb.c:1302
+#: g10/trustdb.c:1101 g10/trustdb.c:1348
#, c-format
msgid "problem finding '%s' in trustdb: %s\n"
msgstr "problemas encontrando '%s' no banco de dados de confiança: %s\n"
-#: g10/trustdb.c:1090
+#: g10/trustdb.c:1104
#, c-format
msgid "user '%s' not in trustdb\n"
msgstr "usuário '%s' não está no banco de dados de confiança\n"
-#: g10/trustdb.c:1125
+#: g10/trustdb.c:1139
#, c-format
msgid ""
"# List of assigned trustvalues, created %s\n"
"# (Use \"gpgm --import-ownertrust\" to restore them)\n"
msgstr ""
"# Lista de valores de confiança designados, criada em %s\n"
"# (Use \"gpgm --import-ownertrust\" para restaurá-los)\n"
-#: g10/trustdb.c:1131
+#: g10/trustdb.c:1145
msgid "directory record w/o primary key\n"
msgstr "registro de diretório sem chave primária\n"
-#: g10/trustdb.c:1138
+#: g10/trustdb.c:1152
#, c-format
msgid "error reading key record: %s\n"
msgstr "erro lendo registro de chave: %s\n"
-#: g10/trustdb.c:1178
+#: g10/trustdb.c:1192
msgid "line too long\n"
msgstr "linha muito longa\n"
-#: g10/trustdb.c:1186
+#: g10/trustdb.c:1200
msgid "error: missing colon\n"
msgstr "erro: falta dois pontos\n"
-#: g10/trustdb.c:1191
+#: g10/trustdb.c:1205
msgid "error: invalid fingerprint\n"
msgstr "erro: impressão digital inválida\n"
-#: g10/trustdb.c:1195
+#: g10/trustdb.c:1209
msgid "error: no ownertrust value\n"
msgstr "erro: nenhum valor de confiança\n"
-#: g10/trustdb.c:1209
+#: g10/trustdb.c:1223
#, c-format
msgid "LID %lu: changing trust from %u to %u\n"
msgstr "LID %lu: mudando confiança de %u para %u\n"
-#: g10/trustdb.c:1212
+#: g10/trustdb.c:1226
#, c-format
msgid "LID %lu: setting trust to %u\n"
msgstr "LID %lu: estabelecendo confiança para %u\n"
-#: g10/trustdb.c:1220
+#: g10/trustdb.c:1234
msgid "key not in trustdb, searching ring.\n"
msgstr ""
"chave não encontrada no banco de dados de confiança, procurando no anel\n"
-#: g10/trustdb.c:1223
+#: g10/trustdb.c:1237
#, c-format
msgid "key not in ring: %s\n"
msgstr "chave não encontrada no anel: %s\n"
-#: g10/trustdb.c:1227
+#: g10/trustdb.c:1241
msgid "Oops: key is now in trustdb???\n"
msgstr "Oops: agora a chave está no banco de dados de confiança???\n"
#. update the ownertrust
-#: g10/trustdb.c:1232
+#: g10/trustdb.c:1246
#, c-format
msgid "insert trust record failed: %s\n"
msgstr "inserção de registro de confiança falhou: %s\n"
#. error
-#: g10/trustdb.c:1238
+#: g10/trustdb.c:1252
#, fuzzy, c-format
msgid "error finding dir record: %s\n"
msgstr "erro encontrando registro de diretório: %s\n"
-#: g10/trustdb.c:1305
+#: g10/trustdb.c:1351
#, c-format
msgid "user '%s' not in trustdb - inserting\n"
msgstr ""
"usuário '%s' não encontrado no banco de dados de confiança - inserindo\n"
-#: g10/trustdb.c:1308
+#: g10/trustdb.c:1354
#, c-format
msgid "failed to put '%s' into trustdb: %s\n"
msgstr "falha ao colocar '%s' no banco de dados de confiança: %s\n"
-#: g10/trustdb.c:1355
+#: g10/trustdb.c:1404
#, c-format
msgid "%s: keyblock read problem: %s\n"
msgstr "%s: erro de leitura de bloco de chaves: %s\n"
-#: g10/trustdb.c:1369
+#: g10/trustdb.c:1418
#, c-format
msgid "%s: update failed: %s\n"
msgstr "%s: atualização falhou: %s\n"
-#: g10/trustdb.c:1372
+#: g10/trustdb.c:1421
#, c-format
msgid "%s: updated\n"
msgstr "%s: atualizado\n"
-#: g10/trustdb.c:1374
+#: g10/trustdb.c:1423
#, c-format
msgid "%s: okay\n"
msgstr "%s: correto\n"
-#: g10/trustdb.c:1389
+#: g10/trustdb.c:1438
#, fuzzy, c-format
msgid "lid %lu: dir record w/o key - skipped\n"
msgstr "lid %lu: registro de diretório sem chave - ignorado\n"
-#: g10/trustdb.c:1402
+#: g10/trustdb.c:1451
#, c-format
msgid "lid %lu: keyblock not found: %s\n"
msgstr "lid %lu: bloco de chaves não encontrado: %s\n"
-#: g10/trustdb.c:1411 g10/trustdb.c:1480
+#: g10/trustdb.c:1460 g10/trustdb.c:1529
#, c-format
msgid "lid %lu: update failed: %s\n"
msgstr "lid %lu: atualização falhou %s\n"
-#: g10/trustdb.c:1417 g10/trustdb.c:1486
+#: g10/trustdb.c:1466 g10/trustdb.c:1535
#, c-format
msgid "lid %lu: updated\n"
msgstr "lid %lu: atualizado\n"
-#: g10/trustdb.c:1421 g10/trustdb.c:1490
+#: g10/trustdb.c:1470 g10/trustdb.c:1539
#, c-format
msgid "lid %lu: okay\n"
msgstr "lid %lu: correto\n"
-#: g10/trustdb.c:1428 g10/trustdb.c:1496
+#: g10/trustdb.c:1477 g10/trustdb.c:1545
#, c-format
msgid "%lu keys processed\n"
msgstr "%lu chaves processadas\n"
-#: g10/trustdb.c:1430
+#: g10/trustdb.c:1479
#, c-format
msgid "\t%lu keys skipped\n"
msgstr "\t%lu chaves ignoradas\n"
-#: g10/trustdb.c:1432 g10/trustdb.c:1498
+#: g10/trustdb.c:1481 g10/trustdb.c:1547
#, c-format
msgid "\t%lu keys with errors\n"
msgstr "\t%lu chaves com erros\n"
-#: g10/trustdb.c:1434 g10/trustdb.c:1500
+#: g10/trustdb.c:1483 g10/trustdb.c:1549
#, c-format
msgid "\t%lu keys updated\n"
msgstr "\t%lu chaves atualizadas\n"
-#: g10/trustdb.c:1464
+#: g10/trustdb.c:1513
#, c-format
msgid "lid ?: insert failed: %s\n"
msgstr "lid ?: inserção falhou: %s\n"
-#: g10/trustdb.c:1469
+#: g10/trustdb.c:1518
#, c-format
msgid "lid %lu: insert failed: %s\n"
msgstr "lid %lu: inserção falhou: %s\n"
-#: g10/trustdb.c:1475
+#: g10/trustdb.c:1524
#, c-format
msgid "lid %lu: inserted\n"
msgstr "lid %lu: inserido\n"
-#: g10/trustdb.c:1502
+#: g10/trustdb.c:1551
#, c-format
msgid "\t%lu keys inserted\n"
msgstr "\t%lu chaves inseridas\n"
-#: g10/trustdb.c:1505
+#: g10/trustdb.c:1554
#, c-format
msgid "enumerate keyblocks failed: %s\n"
msgstr "enumeração de blocos de chaves falhou: %s\n"
-#: g10/trustdb.c:1550
+#: g10/trustdb.c:1599
#, c-format
msgid "check_trust: search dir record failed: %s\n"
msgstr "check_trust: busca de registro de diretório falhou: %s\n"
-#: g10/trustdb.c:1557
+#: g10/trustdb.c:1606
#, c-format
msgid "key %08lX: insert trust record failed: %s\n"
msgstr "chave %08lX: inserção de registro de confiança falhou: %s\n"
-#: g10/trustdb.c:1561
+#: g10/trustdb.c:1610
#, c-format
msgid "key %08lX.%lu: inserted into trustdb\n"
msgstr "chave %08lX.%lu: inserida no banco de dados de confiança\n"
-#: g10/trustdb.c:1569
+#: g10/trustdb.c:1618
#, c-format
msgid "key %08lX.%lu: created in future (time warp or clock problem)\n"
msgstr ""
"chave %08lX.%lu: criada no futuro (viagem no tempo ou problema no relogio)\n"
-#: g10/trustdb.c:1576
+#: g10/trustdb.c:1625
#, c-format
msgid "key %08lX.%lu: expired at %s\n"
msgstr "chave %08lX.%lu: expirada em %s\n"
-#: g10/trustdb.c:1584
+#: g10/trustdb.c:1633
#, c-format
msgid "key %08lX.%lu: trust check failed: %s\n"
msgstr "chave %08lX.%lu: verificação de confiança falhou: %s\n"
-#: g10/trustdb.c:1753 g10/trustdb.c:1782 g10/trustdb.c:2521
+#: g10/trustdb.c:1820 g10/trustdb.c:1849 g10/trustdb.c:2588
msgid "WARNING: can't yet handle long pref records\n"
msgstr "AVISO: ainda é impossível manipular registros de preferências longos\n"
-#: g10/trustdb.c:1804
+#: g10/trustdb.c:1871
#, c-format
msgid "get_dir_record: search_record failed: %s\n"
msgstr "get_dir_record: search_record falhou: %s\n"
-#: g10/trustdb.c:1867
+#: g10/trustdb.c:1934
#, fuzzy, c-format
msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but marked as checked\n"
msgstr ""
"NOTA: assinatura rec %lu[%d] em lista de sugestões de %lu mas marcada\n"
"como verificada\n"
-#: g10/trustdb.c:1871
+#: g10/trustdb.c:1938
#, fuzzy, c-format
msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but not marked\n"
msgstr ""
"NOTA: assinatura rec %lu[%d] em lista de sugestões de %lu mas não\n"
"marcada\n"
#. we need the dir record
-#: g10/trustdb.c:1878
+#: g10/trustdb.c:1945
#, c-format
msgid "sig rec %lu[%d] in hintlist of %lu does not point to a dir record\n"
msgstr ""
"assinatura rec %lu[%d] em lista de sugestões de %lu não aponta para\n"
"um registro de diretório\n"
-#: g10/trustdb.c:1884
+#: g10/trustdb.c:1951
#, c-format
msgid "lid %lu: no primary key\n"
msgstr "lid %lu: nenhuma chave primária\n"
-#: g10/trustdb.c:1917
+#: g10/trustdb.c:1984
#, c-format
msgid "lid %lu: user id not found in keyblock\n"
msgstr "lid %lu: id de usuário não encontrado no bloco de chaves\n"
-#: g10/trustdb.c:1921
+#: g10/trustdb.c:1988
#, c-format
msgid "lid %lu: user id without signature\n"
msgstr "lid %lu: id de usuário sem assinatura\n"
-#: g10/trustdb.c:1928
+#: g10/trustdb.c:1995
#, c-format
msgid "lid %lu: self-signature in hintlist\n"
msgstr "lid %lu: auto-assinatura na lista de sugestões\n"
-#: g10/trustdb.c:1939 g10/trustdb.c:2658 g10/trustdb.c:2742
+#: g10/trustdb.c:2006 g10/trustdb.c:2725 g10/trustdb.c:2809
msgid "Valid certificate revocation"
msgstr "Certificado de revogação válido"
-#: g10/trustdb.c:1940 g10/trustdb.c:2659 g10/trustdb.c:2743
+#: g10/trustdb.c:2007 g10/trustdb.c:2726 g10/trustdb.c:2810
msgid "Good certificate"
msgstr "Certificado correto"
-#: g10/trustdb.c:1949
+#: g10/trustdb.c:2016
msgid "very strange: no public key\n"
msgstr "muito estranho: nenhuma chave pública\n"
-#: g10/trustdb.c:1997
+#: g10/trustdb.c:2064
#, c-format
msgid "hintlist %lu[%d] of %lu does not point to a dir record\n"
msgstr ""
"lista de sugestões %lu[%d] de %lu não aponta para registro de diretório\n"
-#: g10/trustdb.c:2003
+#: g10/trustdb.c:2070
#, c-format
msgid "lid %lu does not have a key\n"
msgstr "lid %lu não tem uma chave\n"
-#: g10/trustdb.c:2013
+#: g10/trustdb.c:2080
#, c-format
msgid "lid %lu: can't get keyblock: %s\n"
msgstr "lid %lu: impossível pegar bloco de chaves: %s\n"
-#: g10/trustdb.c:2070 g10/trustdb.c:2984
+#: g10/trustdb.c:2137 g10/trustdb.c:3051
#, c-format
msgid "tdbio_search_dir failed: %s\n"
msgstr "tdbio_search_dir falhou: %s\n"
-#: g10/trustdb.c:2223
+#: g10/trustdb.c:2290
#, c-format
msgid "key %08lX.%lu: Good subkey binding\n"
msgstr "chave %08lX.%lu: Ligação de subchave válida\n"
-#: g10/trustdb.c:2229 g10/trustdb.c:2271
+#: g10/trustdb.c:2296 g10/trustdb.c:2338
#, c-format
msgid "key %08lX.%lu: Invalid subkey binding: %s\n"
msgstr "chave %08lX.%lu: Ligação de subchave inválida: %s\n"
-#: g10/trustdb.c:2244
+#: g10/trustdb.c:2311
#, c-format
msgid "key %08lX.%lu: Valid key revocation\n"
msgstr "chave %08lX.%lu: Revogação de chave válida\n"
-#: g10/trustdb.c:2250
+#: g10/trustdb.c:2317
#, c-format
msgid "key %08lX.%lu: Invalid key revocation: %s\n"
msgstr "chave %08lX.%lu: Revogação de chave inválida: %s\n"
-#: g10/trustdb.c:2265
+#: g10/trustdb.c:2332
#, c-format
msgid "key %08lX.%lu: Valid subkey revocation\n"
msgstr "chave %08lX.%lu: Revogação de subchave válida\n"
-#: g10/trustdb.c:2365
+#: g10/trustdb.c:2432
msgid "Good self-signature"
msgstr "Auto-assinatura válida"
-#: g10/trustdb.c:2376
+#: g10/trustdb.c:2443
msgid "Invalid self-signature"
msgstr "Auto-assinatura inválida"
-#: g10/trustdb.c:2386
+#: g10/trustdb.c:2453
msgid "Valid user ID revocation skipped due to a newer self signature\n"
msgstr ""
-#: g10/trustdb.c:2393
+#: g10/trustdb.c:2460
msgid "Valid user ID revocation\n"
msgstr "Revogação de ID de usuário válida\n"
-#: g10/trustdb.c:2400
+#: g10/trustdb.c:2467
msgid "Invalid user ID revocation"
msgstr "Revogação de ID de usuário inválida"
-#: g10/trustdb.c:2484
+#: g10/trustdb.c:2551
msgid "Too many preferences"
msgstr "Muitas preferências"
-#: g10/trustdb.c:2498
+#: g10/trustdb.c:2565
msgid "Too many preference items"
msgstr "Muitos itens de preferência"
-#: g10/trustdb.c:2637
+#: g10/trustdb.c:2704
msgid "Duplicated certificate - deleted"
msgstr "Certificado duplicado - deletado"
-#: g10/trustdb.c:2670
+#: g10/trustdb.c:2737
msgid "Hmmm, public key lost?"
msgstr "Hmmm, chave pública perdida?"
-#: g10/trustdb.c:2680 g10/trustdb.c:2763
+#: g10/trustdb.c:2747 g10/trustdb.c:2830
msgid "Invalid certificate revocation"
msgstr "Certificado de revogação inválido"
-#: g10/trustdb.c:2681 g10/trustdb.c:2764
+#: g10/trustdb.c:2748 g10/trustdb.c:2831
msgid "Invalid certificate"
msgstr "Certificado inválido"
-#: g10/trustdb.c:2696
+#: g10/trustdb.c:2763
#, c-format
msgid "uid %08lX.%lu/%02X%02X: has shadow dir %lu but is not yet marked.\n"
msgstr ""
"uid %08lX.%lu/%02X%02X: tem diretório sombra %lu mas ainda não está\n"
"marcado\n"
-#: g10/trustdb.c:2710
+#: g10/trustdb.c:2777
#, c-format
msgid "sig record %lu[%d] points to wrong record.\n"
msgstr "registro de assinatura %lu[%d] aponta para registro errado.\n"
#. that should never happen
-#: g10/trustdb.c:2954
+#: g10/trustdb.c:3021
#, c-format
msgid "insert_trust_record: keyblock not found: %s\n"
msgstr "insert_trust_record: bloco de chaves não encontrado: %s\n"
-#: g10/trustdb.c:2972
+#: g10/trustdb.c:3039
msgid "did not use primary key for insert_trust_record()\n"
msgstr "você usou a chave primária para insert_trust_record()\n"
#: g10/ringedit.c:293
#, c-format
msgid "%s: can't create keyring: %s\n"
msgstr "%s: impossível criar anel de chaves: %s\n"
#: g10/ringedit.c:299 g10/ringedit.c:1264
#, c-format
msgid "%s: keyring created\n"
msgstr "%s: anel de chaves criado\n"
#: g10/ringedit.c:1449
msgid "WARNING: 2 files with confidential information exists.\n"
msgstr "AVISO: 2 arquivos com informações confidenciais existem.\n"
#: g10/ringedit.c:1450
#, c-format
msgid "%s is the unchanged one\n"
msgstr "%s é o não modificado\n"
#: g10/ringedit.c:1451
#, c-format
msgid "%s is the new one\n"
msgstr "%s é o novo\n"
#: g10/ringedit.c:1452
msgid "Please fix this possible security flaw\n"
msgstr "Por favor conserte este possível furo de segurança\n"
#: g10/skclist.c:94
#, c-format
msgid "skipped '%s': %s\n"
msgstr "ignorado '%s': %s\n"
#: g10/skclist.c:100
#, c-format
msgid ""
"skipped '%s': this is a PGP generated ElGamal key which is not secure for "
"signatures!\n"
msgstr ""
"ignorado '%s': esta é uma chave ElGamal gerada pelo PGP que não é segura "
"para assinaturas!\n"
#. do not overwrite
#: g10/openfile.c:58
#, c-format
msgid "File '%s' exists. "
msgstr "Arquivo '%s' existe. "
#: g10/openfile.c:60
msgid "Overwrite (y/N)? "
msgstr "Sobrescrever (s/N)? "
#: g10/openfile.c:85
msgid "writing to stdout\n"
msgstr "escrevendo para \"stdout\"\n"
#: g10/openfile.c:134
#, c-format
msgid "assuming signed data in '%s'\n"
msgstr "assumindo dados assinados em '%s'\n"
#: g10/openfile.c:181
#, c-format
msgid "%s: new options file created\n"
msgstr "%s: novo arquivo de opções criado\n"
#: g10/encr-data.c:59
#, c-format
msgid "%s encrypted data\n"
msgstr "dados codificados com\n"
#: g10/encr-data.c:61
#, c-format
msgid "encrypted with unknown algorithm %d\n"
msgstr "codificado com algoritmo desconhecido %d\n"
#: g10/encr-data.c:74
msgid ""
"WARNING: Message was encrypted with a weak key in the symmetric cipher.\n"
msgstr ""
"AVISO: A mensagem foi codificada com uma chave fraca na criptografia\n"
"simétrica.\n"
#: g10/seskey.c:52
msgid "weak key created - retrying\n"
msgstr "chave fraca criada - tentando novamente\n"
#: g10/seskey.c:57
#, c-format
msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n"
msgstr ""
"impossível evitar chave fraca para criptografia simétrica;\n"
"tentado %d vezes!\n"
#. begin of list
-#: g10/helptext.c:45
+#: g10/helptext.c:48
msgid "edit_ownertrust.value"
msgstr ""
-#: g10/helptext.c:51
+#: g10/helptext.c:54
msgid "revoked_key.override"
msgstr ""
-#: g10/helptext.c:55
+#: g10/helptext.c:58
msgid "untrusted_key.override"
msgstr ""
-#: g10/helptext.c:59
+#: g10/helptext.c:62
msgid "pklist.user_id.enter"
msgstr ""
-#: g10/helptext.c:63
+#: g10/helptext.c:66
msgid "keygen.algo"
msgstr ""
-#: g10/helptext.c:79
+#: g10/helptext.c:82
msgid "keygen.algo.elg_se"
msgstr ""
-#: g10/helptext.c:86
+#: g10/helptext.c:89
msgid "keygen.size"
msgstr ""
-#: g10/helptext.c:90
+#: g10/helptext.c:93
msgid "keygen.size.huge.okay"
msgstr ""
-#: g10/helptext.c:95
+#: g10/helptext.c:98
msgid "keygen.size.large.okay"
msgstr ""
-#: g10/helptext.c:100
+#: g10/helptext.c:103
msgid "keygen.valid"
msgstr ""
-#: g10/helptext.c:104
+#: g10/helptext.c:107
msgid "keygen.valid.okay"
msgstr ""
-#: g10/helptext.c:109
+#: g10/helptext.c:112
msgid "keygen.name"
msgstr ""
-#: g10/helptext.c:114
+#: g10/helptext.c:117
msgid "keygen.email"
msgstr ""
-#: g10/helptext.c:118
+#: g10/helptext.c:121
msgid "keygen.comment"
msgstr ""
-#: g10/helptext.c:123
+#: g10/helptext.c:126
msgid "keygen.userid.cmd"
msgstr ""
-#: g10/helptext.c:132
+#: g10/helptext.c:135
msgid "keygen.sub.okay"
msgstr ""
-#: g10/helptext.c:136
+#: g10/helptext.c:139
msgid "sign_uid.okay"
msgstr ""
-#: g10/helptext.c:141
+#: g10/helptext.c:144
msgid "change_passwd.empty.okay"
msgstr ""
-#: g10/helptext.c:146
+#: g10/helptext.c:149
msgid "keyedit.cmd"
msgstr ""
-#: g10/helptext.c:150
+#: g10/helptext.c:153
msgid "keyedit.save.okay"
msgstr ""
-#: g10/helptext.c:155
+#: g10/helptext.c:158
msgid "keyedit.cancel.okay"
msgstr ""
-#: g10/helptext.c:159
+#: g10/helptext.c:162
msgid "keyedit.sign_all.okay"
msgstr ""
-#: g10/helptext.c:163
+#: g10/helptext.c:166
msgid "keyedit.remove.uid.okay"
msgstr ""
-#: g10/helptext.c:168
+#: g10/helptext.c:171
msgid "keyedit.remove.subkey.okay"
msgstr ""
-#: g10/helptext.c:172
+#: g10/helptext.c:175
msgid "passphrase.enter"
msgstr ""
-#: g10/helptext.c:179
+#: g10/helptext.c:182
msgid "passphrase.repeat"
msgstr ""
-#: g10/helptext.c:183
+#: g10/helptext.c:186
msgid "detached_signature.filename"
msgstr ""
-#: g10/helptext.c:187
+#: g10/helptext.c:190
msgid "openfile.overwrite.okay"
msgstr ""
-#: g10/helptext.c:201
+#: g10/helptext.c:204
msgid "No help available"
msgstr "Nenhuma ajuda disponível"
-#: g10/helptext.c:213
+#: g10/helptext.c:216
#, c-format
msgid "No help available for '%s'"
msgstr "Nenhuma ajuda disponível para '%s'"
diff --git a/po/ru.po b/po/ru.po
index cdd476ceb..307a63134 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -1,3212 +1,3226 @@
# I finished the translation without looking at the contrib directory of
# GPG site. Werner enlightened me about two previous translations and I
# dared to look in them to correct my translation of questionable phrases.
# So I'd like to thank:
# Artem Belevich <artemb@usa.net>
# Alexey Morozov <morozov@iname.com>
# Michael Sobolev <mss@transas.com>, 1998
# Alexey Vyskubov <alexey@alv.stud.pu.ru>, 1998
# QingLong <qinglong@Bolizm> (couldn't send an email to let you know)
msgid ""
msgstr ""
-"POT-Creation-Date: 1998-12-10 20:11+0100\n"
+"POT-Creation-Date: 1998-12-17 18:30+0100\n"
"Content-Type: text/plain; charset=\n"
"Date: 1998-01-26 22:08:36+0100\n"
"From: Gregory Steuck <steuck@iname.com>\n"
"Xgettext-Options: --default-domain=gnupg --directory=.. --add-comments "
"--keyword=_ --keyword=N_ --files-from=./POTFILES.in\n"
"Files: util/secmem.c util/argparse.c cipher/random.c cipher/rand-dummy.c "
"cipher/rand-unix.c cipher/rand-w32.c g10/g10.c g10/pkclist.c g10/keygen.c "
"g10/decrypt.c g10/encode.c g10/import.c g10/keyedit.c g10/keylist.c "
"g10/mainproc.c g10/passphrase.c g10/plaintext.c g10/pref.c g10/seckey-cert.c "
"g10/sig-check.c g10/sign.c g10/trustdb.c g10/verify.c\n"
#: util/secmem.c:77
msgid "Warning: using insecure memory!\n"
msgstr ""
"÷ÎÉÍÁÎÉÅ, ×ÏÚÍÏÖÎÁ ÕÔÅÞËÁ ÓÅËÒÅÔÎÙÈ ÄÁÎÎÙÈ!\n"
"üÔÕ ÐÒÏÂÌÅÍÕ ÍÏÖÎÏ ÒÅÛÉÔØ, ÕÓÔÁÎÏ×É× ÐÒÏÇÒÁÍÍÕ suid(root).\n"
"ïÂÒÁÔÉÔÅÓØ ÄÌÑ ÜÔÏÇÏ Ë ÁÄÍÉÎÉÓÔÒÁÔÏÒÕ ÷ÁÛÅÊ ÓÉÓÔÅÍÙ.\n"
#: util/miscutil.c:143
msgid "yes"
msgstr "ÄÁ(y)"
#: util/miscutil.c:144
msgid "yY"
msgstr "yY"
#: util/errors.c:54
msgid "General error"
msgstr "ïÂÝÁÑ ÏÛÉÂËÁ"
#: util/errors.c:55
msgid "Unknown packet type"
msgstr "îÅÉÚ×ÅÓÔÎÙÊ ÔÉÐ ÐÁËÅÔÁ"
#: util/errors.c:56
msgid "Unknown version"
msgstr "îÅÉÚ×ÅÓÔÎÁÑ ×ÅÒÓÉÑ"
#: util/errors.c:57
msgid "Unknown pubkey algorithm"
msgstr "îÅÉÚ×ÅÓÔÎÙÊ ÁÌÇÏÒÉÔÍ ÛÉÆÒÏ×ÁÎÉÑ Ó ÏÔËÒÙÔÙÍ ËÌÀÞÏÍ"
#: util/errors.c:58
msgid "Unknown digest algorithm"
msgstr "îÅÉÚ×ÅÓÔÎÙÊ ÁÌÇÏÒÉÔÍ ÇÅÎÅÒÁÃÉÉ ÄÁÊÄÖÅÓÔÁ"
#: util/errors.c:59
msgid "Bad public key"
msgstr "ðÌÏÈÏÊ ÏÔËÒÙÔÙÊ ËÌÀÞ"
#: util/errors.c:60
msgid "Bad secret key"
msgstr "ðÌÏÈÏÊ ÓÅËÒÅÔÎÙÊ ËÌÀÞ"
#: util/errors.c:61
msgid "Bad signature"
msgstr "ðÌÏÈÁÑ ÐÏÄÐÉÓØ"
#: util/errors.c:62
msgid "Checksum error"
msgstr "îÅÓÏ×ÐÁÄÅÎÉÅ ËÏÎÔÒÏÌØÎÏÊ ÓÕÍÍÙ"
#: util/errors.c:63
msgid "Bad passphrase"
msgstr "îÅ×ÅÒÎÁÑ \"ËÌÀÞÅ×ÁÑ ÆÒÁÚÁ\""
#: util/errors.c:64
msgid "Public key not found"
msgstr "ïÔËÒÙÔÙÊ ËÌÀÞ ÎÅ ÎÁÊÄÅÎ"
#: util/errors.c:65
msgid "Unknown cipher algorithm"
msgstr "îÅÉÚ×ÅÓÔÎÙÊ ÁÌÇÏÒÉÔÍ ÛÉÆÒÏ×ÁÎÉÑ"
#: util/errors.c:66
msgid "Can't open the keyring"
msgstr "îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ \"Ó×ÑÚËÕ ËÌÀÞÅÊ\""
#: util/errors.c:67
msgid "Invalid packet"
msgstr "îÅÄÏÐÕÓÔÉÍÙÊ ÐÁËÅÔ"
#: util/errors.c:68
msgid "Invalid armor"
msgstr "îÅÄÏÐÕÓÔÉÍÁÑ ASCII-ËÏÄÉÒÏ×ËÁ"
#: util/errors.c:69
msgid "No such user id"
msgstr "îÅÉÚ×ÅÓÔÎÙÊ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÏÌØÚÏ×ÁÔÅÌÑ"
#: util/errors.c:70
msgid "Secret key not available"
msgstr "óÅËÒÅÔÎÙÊ ËÌÀÞ ÎÅ ÓÕÝÅÓÔ×ÕÅÔ"
#: util/errors.c:71
msgid "Wrong secret key used"
msgstr "éÓÐÏÌØÚÏ×ÁÎ ÎÅÐÒÁ×ÉÌØÎÙÊ ÓÅËÒÅÔÎÙÊ ËÌÀÞ"
#: util/errors.c:72
msgid "Not supported"
msgstr "îÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ"
#: util/errors.c:73
msgid "Bad key"
msgstr "ðÌÏÈÏÊ ËÌÀÞ"
#: util/errors.c:74
msgid "File read error"
msgstr "ïÛÉÂËÁ ÞÔÅÎÉÑ ÆÁÊÌÁ"
#: util/errors.c:75
msgid "File write error"
msgstr "ïÛÉÂËÁ ÚÁÐÉÓÉ ÆÁÊÌÁ"
#: util/errors.c:76
msgid "Unknown compress algorithm"
msgstr "îÅÉÚ×ÅÓÔÎÙÊ ÁÌÇÏÒÉÔÍ ÕÐÁËÏ×ËÉ"
#: util/errors.c:77
msgid "File open error"
msgstr "ïÛÉÂËÁ ÏÔËÒÙÔÉÑ ÆÁÊÌÁ"
#: util/errors.c:78
msgid "File create error"
msgstr "ïÛÉÂËÁ ÓÏÚÄÁÎÉÑ ÆÁÊÌÁ"
#: util/errors.c:79
msgid "Invalid passphrase"
msgstr "îÅ×ÅÒÎÁÑ \"ËÌÀÞÅ×ÁÑ ÆÒÁÚÁ\""
#: util/errors.c:80
msgid "Unimplemented pubkey algorithm"
msgstr "îÅÒÅÁÌÉÚÏ×ÁÎÎÙÊ ÁÌÇÏÒÉÔÍ ÛÉÆÒÏ×ÁÎÉÑ Ó ÏÔËÒÙÔÙÍ ËÌÀÞÏÍ"
#: util/errors.c:81
msgid "Unimplemented cipher algorithm"
msgstr "îÅÒÅÁÌÉÚÏ×ÁÎÎÙÊ ÁÌÇÏÒÉÔÍ ÛÉÆÒÏ×ÁÎÉÑ"
#: util/errors.c:82
msgid "Unknown signature class"
msgstr "ðÏÄÐÉÓØ ÎÅÉÚ×ÅÓÔÎÏÇÏ ÔÉÐÁ"
#: util/errors.c:83
msgid "Trust database error"
msgstr "ïÛÉÂËÁ × Trust-DB (ÂÁÚÁ ÄÁÎÎÙÈ ÄÏ×ÅÒÉÑ)"
#: util/errors.c:84
msgid "Bad MPI"
msgstr ""
#: util/errors.c:85
msgid "Resource limit"
msgstr "îÅÄÏÓÔÁÔÏÞÎÏ ÒÅÓÕÒÓÏ×"
#: util/errors.c:86
msgid "Invalid keyring"
msgstr "îÅÄÏÐÕÓÔÉÍÁÑ \"Ó×ÑÚËÁ ËÌÀÞÅÊ\""
#: util/errors.c:87
msgid "Bad certificate"
msgstr "ðÌÏÈÏÊ ÓÅÒÔÉÆÉËÁÔ"
#: util/errors.c:88
msgid "Malformed user id"
msgstr "îÅÄÏÐÕÓÔÉÍÁÑ ÆÏÒÍÁ ÉÄÅÎÔÉÆÉËÁÔÏÒÁ ÐÏÌØÚÏ×ÁÔÅÌÑ"
#: util/errors.c:89
msgid "File close error"
msgstr "ïÛÉÂËÁ ÚÁËÒÙÔÉÑ ÆÁÊÌÁ"
#: util/errors.c:90
msgid "File rename error"
msgstr "ïÛÉÂËÁ ÐÅÒÅÉÍÅÎÏ×ÁÎÉÑ ÆÁÊÌÁ"
#: util/errors.c:91
msgid "File delete error"
msgstr "ïÛÉÂËÁ ÕÄÁÌÅÎÉÑ ÆÁÊÌÁ"
#: util/errors.c:92
msgid "Unexpected data"
msgstr "îÅÏÖÉÄÁÎÎÙÅ ÄÁÎÎÙÅ"
#: util/errors.c:93
msgid "Timestamp conflict"
msgstr "ëÏÎÆÌÉËÔ ×ÒÅÍÅÎÎÙÈ ÏÔÐÅÞÁÔËÏ× (timestamp)"
#: util/errors.c:94
msgid "Unusable pubkey algorithm"
msgstr "îÅÐÒÉÇÏÄÎÙÊ ÄÌÑ ÉÓÐÏÌØÚÏ×ÁÎÉÑ ÁÌÇÏÒÉÔÍ ÏÔËÒÙÔÏÇÏ ËÌÀÞÁ"
#: util/errors.c:95
msgid "File exists"
msgstr "æÁÊÌ ÓÕÝÅÓÔ×ÕÅÔ"
#: util/errors.c:96
msgid "Weak key"
msgstr "óÌÁÂÙÊ ËÌÀÞ"
#: util/logger.c:178
#, fuzzy, c-format
msgid "... this is a bug (%s:%d:%s)\n"
msgstr "ïÊ-ÊÏ ... ÏÛÉÂËÁ × ÐÒÏÇÒÁÍÍÅ (%s:%d:%s)\n"
#: util/logger.c:184
#, c-format
msgid "you found a bug ... (%s:%d)\n"
msgstr "÷Ù ÎÁÛÌÉ ÏÛÉÂËÕ × ÐÒÏÇÒÁÍÍÅ ... (%s:%d)\n"
-#: cipher/random.c:412
+#: cipher/random.c:406
#, fuzzy
msgid "WARNING: using insecure random number generator!!\n"
msgstr "÷ÎÉÍÁÎÉÅ: ÉÓÐÏÌØÚÕÅÔÓÑ ÎÅÎÁÄÅÖÎÙÊ ÇÅÎÅÒÁÔÏÒ ÓÌÕÞÁÊÎÙÈ ÞÉÓÅÌ!\n"
-#: cipher/random.c:413
+#: cipher/random.c:407
msgid ""
"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"
msgstr ""
"éÓÐÏÌØÚÕÅÍÙÊ ÇÅÎÅÒÁÔÏÒ ÓÌÕÞÁÊÎÙÈ ÞÉÓÅÌ -- ÔÏÌØËÏ ÚÁÇÌÕÛËÁ,\n"
"ÞÔÏÂÙ ÓËÏÍÐÉÌÉÒÏ×ÁÔØ ÐÒÏÇÒÁÍÍÕ, ÎÉËÁË ÎÅ ÎÁÄÅÖÎÙÊ çóþ!\n"
"\n"
"îå ðïìøúõêôåóø äáîîùíé óïúäáîîùíé üôïê ðòïçòáííïê!\n"
"\n"
-#: cipher/rndlinux.c:116
+#: cipher/rndlinux.c:118
#, c-format
msgid ""
"\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"
msgstr ""
"\n"
"îÅÄÏÓÔÁÔÏÞÎÏ ÓÌÕÞÁÊÎÙÈ ÄÁÎÎÙÈ. ðÏÖÁÌÕÊÓÔÁ, ÐÏÄÅÌÁÊÔÅ ÞÔÏ-ÎÉÂÕÄØ, ÞÔÏÂÙ\n"
"ïó ÍÏÇÌÁ ÎÁÂÒÁÔØ ÄÏÐÏÌÎÉÔÅÌØÎÙÅ ÓÌÕÞÁÊÎÙÅ ÞÉÓÌÁ! (ÎÕÖÎÏ ÅÝÅ %d ÂÁÊÔ)\n"
-#: g10/g10.c:159
+#: g10/g10.c:160
msgid ""
"@Commands:\n"
" "
msgstr ""
"@ëÏÍÁÎÄÙ:\n"
" "
-#: g10/g10.c:162
+#: g10/g10.c:163
#, fuzzy
msgid "|[file]|make a signature"
msgstr "|[ÆÁÊÌ]|ÓÏÚÄÁÔØ ÐÏÄÐÉÓØ"
-#: g10/g10.c:163
+#: g10/g10.c:164
#, fuzzy
msgid "|[file]|make a clear text signature"
msgstr "|[ÆÁÊÌ]|ÓÏÚÄÁÔØ ÔÅËÓÔÏ×ÕÀ ÐÏÄÐÉÓØ"
-#: g10/g10.c:164
+#: g10/g10.c:165
msgid "make a detached signature"
msgstr "ÓÏÚÄÁÔØ ÏÔÄÅÌØÎÕÀ ÐÏÄÐÉÓØ"
-#: g10/g10.c:165
+#: g10/g10.c:166
msgid "encrypt data"
msgstr "ÚÁÛÉÆÒÏ×ÁÔØ ÄÁÎÎÙÅ"
-#: g10/g10.c:166
+#: g10/g10.c:167
msgid "encryption only with symmetric cipher"
msgstr "ÚÁÛÉÆÒÏ×ÁÔØ ÓÉÍÍÅÔÒÉÞÎÙÍ ÁÌÇÏÒÉÔÍÏÍ"
-#: g10/g10.c:167
+#: g10/g10.c:168
msgid "store only"
msgstr "ÔÏÌØËÏ ÓÏÈÒÁÎÉÔØ"
-#: g10/g10.c:168
+#: g10/g10.c:169
msgid "decrypt data (default)"
msgstr "ÒÁÓÛÉÆÒÏ×ÁÔØ ÄÁÎÎÙÅ (ÐÏ ÕÍÏÌÞÁÎÉÀ)"
-#: g10/g10.c:169
+#: g10/g10.c:170
msgid "verify a signature"
msgstr "ÐÒÏ×ÅÒÉÔØ ÐÏÄÐÉÓØ"
-#: g10/g10.c:171
+#: g10/g10.c:172
msgid "list keys"
msgstr "ÓÐÉÓÏË ËÌÀÞÅÊ"
-#: g10/g10.c:172
+#: g10/g10.c:173
msgid "list keys and signatures"
msgstr "ÓÐÉÓÏË ËÌÀÞÅÊ É ÐÏÄÐÉÓÅÊ"
-#: g10/g10.c:173
+#: g10/g10.c:174
msgid "check key signatures"
msgstr "ÐÒÏ×ÅÒÉÔØ ÐÏÄÐÉÓØ ÎÁ ËÌÀÞÅ"
-#: g10/g10.c:174
+#: g10/g10.c:175
msgid "list keys and fingerprints"
msgstr "ÓÐÉÓÏË ËÌÀÞÅÊ Ó ÉÈ \"ÏÔÐÅÞÁÔËÁÍÉ ÐÁÌØÃÅ×\""
-#: g10/g10.c:175
+#: g10/g10.c:176
msgid "list secret keys"
msgstr "ÓÐÉÓÏË ÓÅËÒÅÔÎÙÈ ËÌÀÞÅÊ"
-#: g10/g10.c:177
+#: g10/g10.c:178
msgid "generate a new key pair"
msgstr "ÓÇÅÎÅÒÉÒÏ×ÁÔØ ÎÏ×ÕÀ ÐÁÒÕ ËÌÀÞÅÊ (ÏÔËÒÙÔÙÊ É ÓÅËÒÅÔÎÙÊ)"
-#: g10/g10.c:179
+#: g10/g10.c:180
msgid "remove key from the public keyring"
msgstr "ÕÄÁÌÉÔØ ËÌÀÞ ÓÏ Ó×ÑÚËÉ"
-#: g10/g10.c:181
+#: g10/g10.c:182
msgid "sign or edit a key"
msgstr "ÐÏÄÐÉÓÁÔØ ÉÌÉ ÒÅÄÁËÔÉÒÏ×ÁÔØ ËÌÀÞ"
-#: g10/g10.c:182
+#: g10/g10.c:183
msgid "generate a revocation certificate"
msgstr "ÓÇÅÎÅÒÉÒÏ×ÁÔØ ÏÔÚÙ×ÁÀÝÉÊ ÓÅÒÔÉÆÉËÁÔ"
-#: g10/g10.c:184
+#: g10/g10.c:185
msgid "export keys"
msgstr "ÜËÓÐÏÒÔÉÒÏ×ÁÔØ ËÌÀÞÉ"
-#: g10/g10.c:187
+#: g10/g10.c:188
msgid "import/merge keys"
msgstr "ÉÍÐÏÒÔÉÒÏ×ÁÔØ/ÄÏÂÁ×ÉÔØ ËÌÀÞÉ"
-#: g10/g10.c:189
+#: g10/g10.c:190
msgid "list only the sequence of packets"
msgstr "ÎÁÐÅÞÁÔÁÔØ ÔÏÌØËÏ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÓÔØ ÐÁËÅÔÏ×"
-#: g10/g10.c:192
+#: g10/g10.c:193
#, fuzzy
msgid "export the ownertrust values"
msgstr "ÜËÓÐÏÒÔÉÒÏ×ÁÔØ ÐÁÒÁÍÅÔÒÙ ÄÏ×ÅÒÉÑ\n"
-#: g10/g10.c:194
+#: g10/g10.c:195
#, fuzzy
msgid "import ownertrust values"
msgstr "ÉÍÐÏÒÔÉÒÏ×ÁÔØ ÐÁÒÁÍÅÔÒÙ ÄÏ×ÅÒÉÑ\n"
-#: g10/g10.c:196
+#: g10/g10.c:197
#, fuzzy
msgid "|[NAMES]|update the trust database"
msgstr "|[éíåîá]|ÐÒÏ×ÅÒÉÔØ ÂÁÚÕ ÄÁÎÎÙÈ ÄÏ×ÅÒÉÑ"
-#: g10/g10.c:198
+#: g10/g10.c:199
msgid "|[NAMES]|check the trust database"
msgstr "|[éíåîá]|ÐÒÏ×ÅÒÉÔØ ÂÁÚÕ ÄÁÎÎÙÈ ÄÏ×ÅÒÉÑ"
-#: g10/g10.c:199
+#: g10/g10.c:200
msgid "fix a corrupted trust database"
msgstr "ÉÓÐÒÁ×ÉÔØ ÒÁÚÒÕÛÅÎÎÕÀ ÂÁÚÕ ÄÁÎÎÙÈ ÄÏ×ÅÒÉÑ"
-#: g10/g10.c:200
+#: g10/g10.c:201
msgid "De-Armor a file or stdin"
msgstr "äÅËÏÄÉÒÏ×ÁÔØ stdin ÉÌÉ ÆÁÊÌ ÉÚ ASCII-ÐÒÅÄÓÔÁ×ÌÅÎÉÑ"
-#: g10/g10.c:201
+#: g10/g10.c:202
msgid "En-Armor a file or stdin"
msgstr "úÁËÏÄÉÒÏ×ÁÔØ stdin ÉÌÉ ÆÁÊÌ × ASCII-ÐÒÅÄÓÔÁ×ÌÅÎÉÅ"
-#: g10/g10.c:202
+#: g10/g10.c:203
msgid "|algo [files]|print message digests"
msgstr "|algo [files]|ÎÁÐÅÞÁÔÁÔØ ÄÁÊÄÖÅÓÔ ÓÏÏÂÝÅÎÉÑ"
-#: g10/g10.c:203
+#: g10/g10.c:204
msgid "print all message digests"
msgstr "ÎÁÐÅÞÁÔÁÔØ ×ÓÅ ÄÁÊÄÖÅÓÔÙ ÓÏÏÂÝÅÎÉÑ"
-#: g10/g10.c:210
+#: g10/g10.c:211
msgid ""
"@\n"
"Options:\n"
" "
msgstr ""
"@\n"
"ðÁÒÁÍÅÔÒÙ:\n"
" "
-#: g10/g10.c:212
+#: g10/g10.c:213
msgid "create ascii armored output"
msgstr "×Ù×ÏÄ × ASCII-ÐÒÅÄÓÔÁ×ÌÅÎÉÉ"
-#: g10/g10.c:214
+#: g10/g10.c:215
msgid "use this user-id to sign or decrypt"
msgstr ""
"ÉÓÐÏÌØÚÏ×ÁÔØ ÕËÁÚÁÎÎÙÊ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÏÌØÚÏ×ÁÔÅÌÑ ÄÌÑ ÐÏÄÐÉÓÉ ÉÌÉ ÒÁÓÛÉÆÒÏ×ËÉ"
-#: g10/g10.c:215
+#: g10/g10.c:216
msgid "use this user-id for encryption"
msgstr "ÉÓÐÏÌØÚÏ×ÁÔØ ÕËÁÚÁÎÎÙÊ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÏÌØÚÏ×ÁÔÅÌÑ ÄÌÑ ÛÉÆÒÏ×ÁÎÉÑ"
-#: g10/g10.c:216
+#: g10/g10.c:217
msgid "|N|set compress level N (0 disables)"
msgstr "|N|ÕÓÔÁÎÏ×ÉÔØ ÕÒÏ×ÅÎØ ÓÖÁÔÉÑ (0 - ÎÅ ÓÖÉÍÁÔØ)"
-#: g10/g10.c:218
+#: g10/g10.c:219
msgid "use canonical text mode"
msgstr "ÉÓÐÏÌØÚÏ×ÁÔØ ËÁÎÏÎÉÞÅÓËÉÊ ÔÅËÓÔÏ×ÙÊ ÒÅÖÉÍ"
-#: g10/g10.c:220
+#: g10/g10.c:221
msgid "use as output file"
msgstr "ÉÓÐÏÌØÚÏ×ÁÔØ × ËÁÞÅÓÔ×Å ×ÙÈÏÄÎÏÇÏ ÆÁÊÌÁ"
-#: g10/g10.c:221
+#: g10/g10.c:222
msgid "verbose"
msgstr "ÍÎÏÇÏÓÌÏ×ÎÙÊ"
-#: g10/g10.c:222
+#: g10/g10.c:223
msgid "be somewhat more quiet"
msgstr ""
-#: g10/g10.c:223
+#: g10/g10.c:224
#, fuzzy
msgid "force v3 signatures"
msgstr "ÐÒÏ×ÅÒÉÔØ ÐÏÄÐÉÓØ ÎÁ ËÌÀÞÅ"
#. { oDryRun, "dry-run", 0, N_("do not make any changes") },
-#: g10/g10.c:225
+#: g10/g10.c:226
msgid "batch mode: never ask"
msgstr "ÐÁËÅÔÎÙÊ ÒÅÖÉÍ: ÎÉÞÅÇÏ ÎÅ ÓÐÒÁÛÉ×ÁÔØ"
-#: g10/g10.c:226
+#: g10/g10.c:227
msgid "assume yes on most questions"
msgstr "ÏÔ×ÅÞÁÔØ \"ÄÁ\" ÎÁ ÂÏÌØÛÉÎÓÔ×Ï ×ÏÐÒÏÓÏ×"
-#: g10/g10.c:227
+#: g10/g10.c:228
msgid "assume no on most questions"
msgstr "ÏÔ×ÅÞÁÔØ \"ÎÅÔ\" ÎÁ ÂÏÌØÛÉÎÓÔ×Ï ×ÏÐÒÏÓÏ×"
-#: g10/g10.c:228
+#: g10/g10.c:229
msgid "add this keyring to the list of keyrings"
msgstr "ÄÏÂÁ×ÉÔØ ÜÔÕ Ó×ÑÚËÕ Ë ÓÐÉÓËÕ Ó×ÑÚÏË ËÌÀÞÅÊ"
-#: g10/g10.c:229
+#: g10/g10.c:230
msgid "add this secret keyring to the list"
msgstr "ÄÏÂÁ×ÉÔØ ÜÔÕ ÓÅËÒÅÔÎÕÀ Ó×ÑÚËÕ Ë ÓÐÉÓËÕ Ó×ÑÚÏË ËÌÀÞÅÊ"
-#: g10/g10.c:230
+#: g10/g10.c:231
msgid "|NAME|use NAME as default secret key"
msgstr "|éíñ|ÉÓÐÏÌØÚÏ×ÁÔØ éíñ × ËÁÞÅÓÔ×Å ÓÅËÒÅÔÎÏÇÏ ËÌÀÞÁ ÐÏ ÕÍÏÌÞÁÎÉÀ"
-#: g10/g10.c:231
+#: g10/g10.c:232
#, fuzzy
msgid "|NAME|set terminal charset to NAME"
msgstr "|éíñ|ÉÓÐÏÌØÚÏ×ÁÔØ ÛÉÆÒÏ×ÁÌØÎÙÊ ÁÌÇÏÒÉÔÍÏÍ éíñ"
-#: g10/g10.c:232
+#: g10/g10.c:233
msgid "read options from file"
msgstr "ÞÉÔÁÔØ ÐÁÒÁÍÅÔÒÙ ÉÚ ÆÁÊÌÁ"
-#: g10/g10.c:234
+#: g10/g10.c:235
msgid "set debugging flags"
msgstr "ÕÓÔÁÎÏ×ÉÔØ ÏÔÌÁÄÏÞÎÙÅ ÆÌÁÇÉ"
-#: g10/g10.c:235
+#: g10/g10.c:236
msgid "enable full debugging"
msgstr "ÒÁÚÒÅÛÉÔØ ×ÓÀ ÏÔÌÁÄËÕ"
-#: g10/g10.c:236
+#: g10/g10.c:237
msgid "|FD|write status info to this FD"
msgstr "|FD| ÚÁÐÉÓÙ×ÁÔØ ÉÎÆÏÒÍÁÃÉÀ Ï ÓÏÓÔÏÑÎÉÉ × ÄÅÓËÒÉÐÔÏÒ (FD)"
-#: g10/g10.c:237
+#: g10/g10.c:238
msgid "do not write comment packets"
msgstr "ÎÅ ÐÉÓÁÔØ ÐÁËÅÔÙ Ó ËÏÍÍÅÎÔÁÒÉÑÍÉ"
-#: g10/g10.c:238
+#: g10/g10.c:239
msgid "(default is 1)"
msgstr "(ÐÏ ÕÍÏÌÞÁÎÉÀ 1)"
-#: g10/g10.c:239
+#: g10/g10.c:240
msgid "(default is 3)"
msgstr "(ÐÏ ÕÍÏÌÞÁÎÉÀ 3)"
-#: g10/g10.c:241
+#: g10/g10.c:242
msgid "|KEYID|ulimately trust this key"
msgstr ""
-#: g10/g10.c:242
+#: g10/g10.c:243
#, fuzzy
msgid "|FILE|load extension module FILE"
msgstr "|æáêì|ÚÁÇÒÕÚÉÔØ æáêì Ó ÒÁÓÛÉÒÑÀÝÉÍÉ ÍÏÄÕÌÑÍÉ"
-#: g10/g10.c:243
+#: g10/g10.c:244
msgid "emulate the mode described in RFC1991"
msgstr "ÜÍÕÌÉÒÏ×ÁÔØ ÒÅÖÉÍ ÏÐÉÓÁÎÎÙÊ × RFC1991"
-#: g10/g10.c:244
+#: g10/g10.c:245
#, fuzzy
msgid "|N|use passphrase mode N"
msgstr "|N|ÉÓÐÏÌØÚÏ×ÁÔØ ËÌÀÞÅ×ÕÀ ÆÒÁÚÕ ÒÅÖÉÍÁ N\n"
-#: g10/g10.c:246
+#: g10/g10.c:247
#, fuzzy
msgid "|NAME|use message digest algorithm NAME for passphrases"
msgstr "|éíñ|ÉÓÐÏÌØÚÏ×ÁÔØ ÈÜÛ-ÁÌÇÏÒÉÔÍ éíñ ÄÌÑ ËÌÀÞÅ×ÙÈ ÆÒÁÚ"
-#: g10/g10.c:248
+#: g10/g10.c:249
#, fuzzy
msgid "|NAME|use cipher algorithm NAME for passphrases"
msgstr "|éíñ|ÉÓÐÏÌØÚÏ×ÁÔØ ÛÉÆÒÏ×ÁÌØÎÙÊ ÁÌÇÏÒÉÔÍÏÍ éíñ ÄÌÑ ËÌÀÞÅ×ÙÈ ÆÒÁÚ"
-#: g10/g10.c:250
+#: g10/g10.c:251
msgid "|NAME|use cipher algorithm NAME"
msgstr "|éíñ|ÉÓÐÏÌØÚÏ×ÁÔØ ÛÉÆÒÏ×ÁÌØÎÙÊ ÁÌÇÏÒÉÔÍÏÍ éíñ"
-#: g10/g10.c:251
+#: g10/g10.c:252
msgid "|NAME|use message digest algorithm NAME"
msgstr "|éíñ|ÉÓÐÏÌØÚÏ×ÁÔØ ÈÜÛ-ÁÌÇÏÒÉÔÍ éíñ"
-#: g10/g10.c:252
+#: g10/g10.c:253
msgid "|N|use compress algorithm N"
msgstr "|N|ÉÓÐÏÌØÚÏ×ÁÔØ ÁÌÇÏÒÉÔÍ ÓÖÁÔÉÑ N"
-#: g10/g10.c:253
+#: g10/g10.c:254
msgid "throw keyid field of encrypted packets"
msgstr "×ÙÂÒÁÓÙ×ÁÔØ ÐÏÌÅ keyid Õ ÚÁÛÉÆÒÏ×ÁÎÎÙÈ ÐÁËÅÔÏ×"
-#: g10/g10.c:261
+#: g10/g10.c:262
#, fuzzy
msgid ""
"@\n"
"Examples:\n"
"\n"
" -se -r Bob [file] sign and encrypt for user Bob\n"
" --clearsign [file] make a clear text signature\n"
" --detach-sign [file] make a detached signature\n"
" --list-keys [names] show keys\n"
" --fingerprint [names] show fingerprints\n"
msgstr ""
"@\n"
"ðÒÉÍÅÒÙ:\n"
"\n"
" -se -r Bob [file] ÐÏÄÐÉÓÁÔØ É ÚÁÛÉÆÒÏ×ÁÔØ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ Bob\n"
" --clearsign [file] ÓÄÅÌÁÔØ ÔÅËÓÔÏ×ÕÀ ÐÏÄÐÉÓØ\n"
" --detach-sign [file] ÓÄÅÌÁÔØ ÏÔÄÅÌØÎÕÀ ÐÏÄÐÉÓØ\n"
" --list-keys [names] ÐÏËÁÚÁÔØ ÓÐÉÓÏË ËÌÀÞÅÊ\n"
" --fingerprint [names] ÐÏËÁÚÁÔØ \"ÏÔÐÅÞÁÔËÉ ÐÁÌØÃÅ×\" ËÌÀÞÅÊ\n"
-#: g10/g10.c:339
+#: g10/g10.c:341
msgid "Please report bugs to <gnupg-bugs@gnu.org>.\n"
msgstr ""
"ðÏÖÁÌÕÊÓÔÁ, ÏÔÐÒÁ×ÌÑÊÔÅ ÓÏÏÂÝÅÎÉÑ Ï ÏÛÉÂËÁÈ ÐÏ ÁÄÒÅÓÕ "
"<gnupg-bugs@gnu.org>.\n"
-#: g10/g10.c:344
+#: g10/g10.c:346
msgid "Usage: gpgm [options] [files] (-h for help)"
msgstr "éÓÐÏÌØÚÏ×ÁÎÉÅ: gpgm [ÐÁÒÁÍÅÔÒÙ] [ÆÁÊÌÙ] (-h ÄÌÑ ÐÏÍÏÝÉ)"
-#: g10/g10.c:346
+#: g10/g10.c:348
msgid "Usage: gpg [options] [files] (-h for help)"
msgstr "éÓÐÏÌØÚÏ×ÁÎÉÅ: gpg [ÐÁÒÁÍÅÔÒÙ] [ÆÁÊÌÙ] (-h ÄÌÑ ÐÏÍÏÝÉ)"
-#: g10/g10.c:351
+#: g10/g10.c:353
#, fuzzy
msgid ""
"Syntax: gpgm [options] [files]\n"
"GnuPG maintenance utility\n"
msgstr ""
"óÉÎÔÁËÓÉÓ: gpgm [ÐÁÒÁÍÅÔÒÙ] [ÆÁÊÌÙ]\n"
"ðÒÏÇÒÁÍÍÁ ÓÏÐÒÏ×ÏÖÄÅÎÉÑ GNUPG\n"
-#: g10/g10.c:354
+#: g10/g10.c:356
msgid ""
"Syntax: gpg [options] [files]\n"
"sign, check, encrypt or decrypt\n"
"default operation depends on the input data\n"
msgstr ""
"óÉÎÔÁËÓÉÓ: gpg [ÐÁÒÁÍÅÔÒÙ] [ÆÁÊÌÙ]\n"
"ÐÏÄÐÉÓÙ×ÁÅÔ, ÐÒÏ×ÅÒÑÅÔ ÐÏÄÐÉÓÉ, ÛÉÆÒÕÅÔ ÉÌÉ ÒÁÓÛÉÆÒÏ×Ù×ÁÅÔ\n"
"ÒÅÖÉÍ ÒÁÂÏÔÙ ÚÁ×ÉÓÉÔ ÏÔ ×ÈÏÄÎÙÈ ÄÁÎÎÙÈ\n"
-#: g10/g10.c:360
+#: g10/g10.c:362
msgid ""
"\n"
"Supported algorithms:\n"
msgstr ""
"\n"
"ðÏÄÄÅÒÖÉ×ÁÅÍÙÅ ÁÌÇÏÒÉÔÍÙ:\n"
-#: g10/g10.c:435
+#: g10/g10.c:437
msgid "usage: gpgm [options] "
msgstr "éÓÐÏÌØÚÏ×ÁÎÉÅ: gpgm [ÐÁÒÁÍÅÔÒÙ] "
-#: g10/g10.c:437
+#: g10/g10.c:439
msgid "usage: gpg [options] "
msgstr "éÓÐÏÌØÚÏ×ÁÎÉÅ: gpg [ÐÁÒÁÍÅÔÒÙ] "
-#: g10/g10.c:478
+#: g10/g10.c:480
msgid "conflicting commands\n"
msgstr "Widersprüchliche Kommandos\n"
-#: g10/g10.c:616
+#: g10/g10.c:618
#, fuzzy, c-format
msgid "NOTE: no default option file '%s'\n"
msgstr "ÚÁÍÅÞÁÎÉÅ: ÆÁÊÌ ÐÁÒÁÍÅÔÒÏ× ÐÏ ÕÍÏÌÞÁÎÉÀ '%s' ÏÔÓÕÔÓÔ×ÕÅÔ\n"
-#: g10/g10.c:620
+#: g10/g10.c:622
#, c-format
msgid "option file '%s': %s\n"
msgstr "ÆÁÊÌ ÐÁÒÁÍÅÔÒÏ× '%s': %s\n"
-#: g10/g10.c:627
+#: g10/g10.c:629
#, c-format
msgid "reading options from '%s'\n"
msgstr "ÞÉÔÁÀÔÓÑ ÐÁÒÁÍÅÔÒÙ ÉÚ '%s'\n"
-#: g10/g10.c:776
+#: g10/g10.c:782
#, fuzzy, c-format
msgid "%s is not a valid character set\n"
msgstr "îÅÄÏÐÕÓÔÉÍÙÊ ÓÉÍ×ÏÌ × ËÏÍÍÅÎÔÁÒÉÉ.\n"
-#: g10/g10.c:810 g10/g10.c:822
+#: g10/g10.c:817 g10/g10.c:829
msgid "selected cipher algorithm is invalid\n"
msgstr "×ÙÂÒÁÎ ÎÅÄÏÐÕÓÔÉÍÙÊ ÁÌÇÏÒÉÔÍ ÛÉÆÒÏ×ÁÎÉÑ\n"
-#: g10/g10.c:816 g10/g10.c:828
+#: g10/g10.c:823 g10/g10.c:835
msgid "selected digest algorithm is invalid\n"
msgstr "×ÙÂÒÁÎ ÎÅÄÏÐÕÓÔÉÍÙÊ ÄÁÊÄÖÅÓÔ-ÁÌÇÏÒÉÔÍ\n"
-#: g10/g10.c:831
+#: g10/g10.c:838
#, c-format
msgid "compress algorithm must be in range %d..%d\n"
msgstr "ÁÌÇÏÒÉÔÍ ÕÐÁËÏ×ËÉ ÍÏÖÅÔ ÉÍÅÔØ ÚÎÁÞÅÎÉÑ ÏÔ %d ÄÏ %d\n"
-#: g10/g10.c:833
+#: g10/g10.c:840
msgid "completes-needed must be greater than 0\n"
msgstr "completes-needed ÄÏÌÖÅÎ ÂÙÔØ ÂÏÌØÛÅ 0\n"
-#: g10/g10.c:835
+#: g10/g10.c:842
msgid "marginals-needed must be greater than 1\n"
msgstr "marginals-needed ÄÏÌÖÅÎ ÂÙÔØ ÂÏÌØÛÅ 1\n"
-#: g10/g10.c:837
+#: g10/g10.c:844
msgid "max-cert-depth must be in range 1 to 255\n"
msgstr ""
-#: g10/g10.c:840
+#: g10/g10.c:847
#, fuzzy
msgid "NOTE: simple S2K mode (0) is strongly discouraged\n"
msgstr "ÚÁÍÅÞÁÎÉÅ: ÐÒÏÓÔÏÊ S2K ÒÅÖÉÍ (0) ÏÞÅÎØ ÎÅ ÒÅËÏÍÅÎÄÕÅÔÓÑ\n"
-#: g10/g10.c:844
+#: g10/g10.c:851
msgid "invalid S2K mode; must be 0, 1 or 3\n"
msgstr "ÎÅÄÏÐÕÓÔÉÍÙÊ ÒÅÖÉÍ S2K: ÄÏÌÖÅÎ ÂÙÔØ 0, 1 ÉÌÉ 3\n"
-#: g10/g10.c:927
+#: g10/g10.c:934
#, c-format
msgid "failed to initialize the TrustDB: %s\n"
msgstr "ïÛÉÂËÁ ÉÎÉÃÉÁÌÉÚÁÃÉÉ ÂÁÚÙ ÄÁÎÎÙÈ ÄÏ×ÅÒÉÑ: %s\n"
-#: g10/g10.c:933
+#: g10/g10.c:940
msgid "--store [filename]"
msgstr "--store [ÉÍÑ ÆÁÊÌÁ]"
-#: g10/g10.c:941
+#: g10/g10.c:948
msgid "--symmetric [filename]"
msgstr "--symmetric [ÉÍÑ ÆÁÊÌÁ]"
-#: g10/g10.c:949
+#: g10/g10.c:956
msgid "--encrypt [filename]"
msgstr "--encrypt [ÉÍÑ ÆÁÊÌÁ]"
-#: g10/g10.c:962
+#: g10/g10.c:969
msgid "--sign [filename]"
msgstr "--sign [ÉÍÑ ÆÁÊÌÁ]"
-#: g10/g10.c:975
+#: g10/g10.c:982
msgid "--sign --encrypt [filename]"
msgstr "--sign --encrypt [ÉÍÑ ÆÁÊÌÁ]"
-#: g10/g10.c:989
+#: g10/g10.c:996
msgid "--clearsign [filename]"
msgstr "--clearsign [ÉÍÑ ÆÁÊÌÁ]"
-#: g10/g10.c:1001
+#: g10/g10.c:1008
msgid "--decrypt [filename]"
msgstr "--decrypt [ÉÍÑ ÆÁÊÌÁ]"
-#: g10/g10.c:1010
+#: g10/g10.c:1017
#, fuzzy
msgid "--edit-key username [commands]"
msgstr "--edit-key ÉÍÑ-ÐÏÌØÚÏ×ÁÔÅÌÑ"
-#: g10/g10.c:1026
+#: g10/g10.c:1033
msgid "--delete-secret-key username"
msgstr "--delete-secret-key ÉÍÑ-ÐÏÌØÚÏ×ÁÔÅÌÑ"
-#: g10/g10.c:1029
+#: g10/g10.c:1036
msgid "--delete-key username"
msgstr "--delete-key ÉÍÑ-ÐÏÌØÚÏ×ÁÔÅÌÑ"
-#: g10/encode.c:216 g10/g10.c:1052 g10/sign.c:301
+#: g10/encode.c:216 g10/g10.c:1059 g10/sign.c:301
#, c-format
msgid "can't open %s: %s\n"
msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ '%s': %s\n"
-#: g10/g10.c:1063
+#: g10/g10.c:1070
msgid "-k[v][v][v][c] [userid] [keyring]"
msgstr "-k[v][v][v][c] [ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÏÌØÚÏ×ÁÔÅÌÑ] [Ó×ÑÚËÁ ËÌÀÞÅÊ]"
-#: g10/g10.c:1120
+#: g10/g10.c:1127
#, c-format
msgid "dearmoring failed: %s\n"
msgstr "ÏÛÉÂËÁ ÄÅËÏÄÉÒÏ×ÁÎÉÑ: %s\n"
-#: g10/g10.c:1128
+#: g10/g10.c:1135
#, c-format
msgid "enarmoring failed: %s\n"
msgstr "ÏÛÉÂËÁ ËÏÄÉÒÏ×ÁÎÉÑ: %s\n"
-#: g10/g10.c:1194
+#: g10/g10.c:1201
#, c-format
msgid "invalid hash algorithm '%s'\n"
msgstr "ÎÅÄÏÐÕÓÔÉÍÙÊ ÈÜÛ-ÁÌÇÏÒÉÔÍ '%s'\n"
-#: g10/g10.c:1273
+#: g10/g10.c:1280
msgid "[filename]"
msgstr "[ÉÍÑ ÆÁÊÌÁ]"
-#: g10/g10.c:1277
+#: g10/g10.c:1284
msgid "Go ahead and type your message ...\n"
msgstr ""
-#: g10/decrypt.c:59 g10/g10.c:1280 g10/verify.c:66
+#: g10/decrypt.c:59 g10/g10.c:1287 g10/verify.c:66
#, c-format
msgid "can't open '%s'\n"
msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ '%s'\n"
#: g10/armor.c:344 g10/armor.c:391
msgid "armor header: "
msgstr ""
#: g10/armor.c:355
#, fuzzy
msgid "invalid clearsig header\n"
msgstr "ÎÅÄÏÐÕÓÔÉÍÏÅ ÎÁÞÁÌÏ ÔÅËÓÔÏ×ÏÊ ÐÏÄÐÉÓÉ\n"
#: g10/armor.c:382
msgid "invalid armor header: "
msgstr ""
#: g10/armor.c:460
#, fuzzy, c-format
msgid "armor: %s\n"
msgstr "ëÏÄÉÒÏ×ËÁ: %s\n"
#: g10/armor.c:533
msgid "invalid dash escaped line: "
msgstr "ÎÅÄÏÐÕÓÔÉÍÁÑ ÓÔÒÏËÁ ÎÁÞÉÎÁÀÝÁÑÓÑ Ó ÍÉÎÕÓÏ×: "
#: g10/armor.c:602
msgid "invalid clear text header: "
msgstr "ÎÅÄÏÐÕÓÔÉÍÙÊ ÔÅËÓÔÏ×ÙÊ ÚÁÇÏÌÏ×ÏË: "
#: g10/armor.c:845
#, fuzzy, c-format
msgid "invalid radix64 character %02x skipped\n"
msgstr "ÎÅÄÏÐÕÓÔÉÍÙÊ ÄÌÑ ËÏÄÉÒÏ×ËÉ radix64 ÓÉÍ×ÏÌ %02x ÐÒÏÐÕÝÅÎ\n"
#: g10/armor.c:878
msgid "premature eof (no CRC)\n"
msgstr "ÎÅÏÖÉÄÁÎÎÙÊ ËÏÎÅÃ ÆÁÊÌÁ (ÎÅÔ CRC)\n"
#: g10/armor.c:897
msgid "premature eof (in CRC)\n"
msgstr "ÎÅÏÖÉÄÁÎÎÙÊ ËÏÎÅÃ ÆÁÊÌÁ (× CRC)\n"
#: g10/armor.c:901
msgid "malformed CRC\n"
msgstr "ÎÅÐÒÁ×ÉÌØÎÁÑ ÆÏÒÍÁ CRC\n"
#: g10/armor.c:905
#, c-format
msgid "CRC error; %06lx - %06lx\n"
msgstr "ÏÛÉÂËÁ CRC; %06lx - %06lx\n"
#: g10/armor.c:924
msgid "premature eof (in Trailer)\n"
msgstr "ÎÅÏÖÉÄÁÎÎÙÊ ËÏÎÅà ÆÁÊÌÁ (× È×ÏÓÔÅ)\n"
#: g10/armor.c:928
msgid "error in trailer line\n"
msgstr "ÏÛÉÂËÁ × ÚÁ×ÅÒÛÁÀÝÅÊ ÓÔÒÏËÅ\n"
#: g10/armor.c:1182
msgid "no valid RFC1991 or OpenPGP data found.\n"
msgstr "ÎÅ ÎÁÊÄÅÎÏ ÄÏÐÕÓÔÉÍÙÈ RFC1991 ÉÌÉ OpenPGP ÄÁÎÎÙÈ.\n"
-#: g10/pkclist.c:121
+#: g10/pkclist.c:138
#, fuzzy, c-format
msgid ""
"No trust value assigned to %lu:\n"
"%4u%c/%08lX %s \""
msgstr ""
"îÅ ÏÐÒÅÄÅÌÅÎÙ ÐÁÒÁÍÅÔÒÙ ÄÏ×ÅÒÉÑ ÄÌÑ %lu:\n"
"%4u%c/%08lX %s \""
-#: g10/pkclist.c:131
+#: g10/pkclist.c:148
#, fuzzy
msgid ""
"Please decide how far you trust this user to correctly\n"
"verify other users' keys (by looking at passports,\n"
"checking fingerprints from different sources...)?\n"
"\n"
" 1 = Don't know\n"
" 2 = I do NOT trust\n"
" 3 = I trust marginally\n"
" 4 = I trust fully\n"
" s = please show me more information\n"
msgstr ""
"\"\n"
"\n"
"ðÏÖÁÌÕÊÓÔÁ ÒÅÛÉÔÅ, ÎÁÓËÏÌØËÏ ×Ù ÄÏ×ÅÒÑÅÔÅ ÜÔÏÍÕ ÐÏÌØÚÏ×ÁÔÅÌÀ ÐÒÏ×ÅÒÑÔØ\n"
"ÞÕÖÉÅ ËÌÀÞÉ (ÇÌÑÄÑ × ÐÁÓÐÏÒÔÁ, ÐÒÏ×ÅÒÑÑ \"ÏÔÐÅÞÁÔËÉ ÐÁÌØÃÅ×\" ÐÏ ÄÒÕÇÉÍ\n"
"ÉÓÔÏÞÎÉËÁÍ)?\n"
"\n"
" 1 = îÅ ÚÎÁÀ\n"
" 2 = îÅÔ, ÎÅ ÄÏ×ÅÒÑÀ\n"
" 3 = ÷ÅÒÀ ÏÔÞÁÓÔÉ\n"
" 4 = ÷ÅÒÀ ÐÏÌÎÏÓÔØÀ\n"
" s = ðÏÖÁÌÕÊÓÔÁ, ÐÏËÁÖÉÔÅ ÄÏÐÏÌÎÉÔÅÌØÎÕÀ ÉÎÆÏÒÍÁÃÉÀ\n"
-#: g10/pkclist.c:140
+#: g10/pkclist.c:157
msgid " m = back to the main menu\n"
msgstr " m = ÏÂÒÁÔÎÏ × ÇÌÁ×ÎÏÅ ÍÅÎÀ\n"
+#: g10/pkclist.c:159
+msgid " q = quit\n"
+msgstr ""
+
# valid user replies (not including 1..4)
#. a string with valid answers
-#: g10/pkclist.c:145
-msgid "sSmM"
-msgstr "sSmM"
+#: g10/pkclist.c:164
+#, fuzzy
+msgid "sSmMqQ"
+msgstr "sSmMqQ"
-#: g10/pkclist.c:149
+#: g10/pkclist.c:168
msgid "Your decision? "
msgstr "÷ÁÛÅ ÒÅÛÅÎÉÅ? "
-#: g10/pkclist.c:169
+#: g10/pkclist.c:188
msgid "Certificates leading to an ultimately trusted key:\n"
msgstr ""
-#: g10/pkclist.c:197
+#: g10/pkclist.c:221
msgid ""
"Could not find a valid trust path to the key. Let's see whether we\n"
"can assign some missing owner trust values.\n"
"\n"
msgstr ""
"îÅ ÐÏÌÕÞÉÌÏÓØ ÎÁÊÔÉ ÃÅÐÏÞËÕ ÄÏ×ÅÒÉÑ ÄÌÑ ËÌÀÞÁ. ðÏÓÍÏÔÒÉÍ, ÍÏÖÎÏ ÌÉ "
"ÐÒÉÓ×ÏÉÔØ\n"
"ÎÅËÏÔÏÒÙÅ ÎÅÄÏÓÔÁÀÝÉÅ ÚÎÁÞÅÎÉÑ \"ÄÏ×ÅÒÉÑ ×ÌÁÄÅÌØÃÕ\"\n"
"\n"
-#: g10/pkclist.c:219
+#: g10/pkclist.c:251
msgid ""
"No path leading to one of our keys found.\n"
"\n"
msgstr ""
-#: g10/pkclist.c:221
+#: g10/pkclist.c:253
msgid ""
"No certificates with undefined trust found.\n"
"\n"
msgstr ""
-#: g10/pkclist.c:223
+#: g10/pkclist.c:255
#, fuzzy
msgid ""
"No trust values changed.\n"
"\n"
msgstr "úÎÁÞÅÎÉÑ ÐÁÒÁÍÅÔÒÏ× ÄÏ×ÅÒÉÑ ÎÅ ÉÚÍÅÎÅÎÙ.\n"
-#: g10/pkclist.c:238
+#: g10/pkclist.c:270
#, fuzzy, c-format
msgid "key %08lX: key has been revoked!\n"
msgstr "build_sigrecs: ËÌÀÞ ist widerrufen\n"
-#: g10/pkclist.c:244 g10/pkclist.c:335
+#: g10/pkclist.c:276 g10/pkclist.c:369
msgid "Use this key anyway? "
msgstr "÷ÓÅ ÒÁ×ÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ ÜÔÏÔ ËÌÀÞ?"
-#: g10/pkclist.c:266
+#: g10/pkclist.c:298
#, fuzzy, c-format
msgid "%08lX: key has expired\n"
msgstr "úÁÍÅÞÁÎÉÅ: óÒÏË ÄÅÊÓÔ×ÉÑ ËÌÀÞÁ ÕÖÅ ÉÓÔÅË!\n"
-#: g10/pkclist.c:272
+#: g10/pkclist.c:304
#, c-format
msgid "%08lX: no info to calculate a trust probability\n"
msgstr ""
-#: g10/pkclist.c:288
+#: g10/pkclist.c:322
#, fuzzy, c-format
msgid "%08lX: We do NOT trust this key\n"
msgstr "÷îéíáîéå: íÙ îå ÄÏ×ÅÒÑÅÍ ÜÔÏÍÕ ËÌÀÞÕ!\n"
-#: g10/pkclist.c:294
+#: g10/pkclist.c:328
#, c-format
msgid ""
"%08lX: It is not sure that this key really belongs to the owner\n"
"but it is accepted anyway\n"
msgstr ""
-#: g10/pkclist.c:300
+#: g10/pkclist.c:334
msgid "This key probably belongs to the owner\n"
msgstr ""
-#: g10/pkclist.c:305
+#: g10/pkclist.c:339
msgid "This key belongs to us\n"
msgstr ""
-#: g10/pkclist.c:330
+#: g10/pkclist.c:364
msgid ""
"It is NOT certain that the key belongs to its owner.\n"
"If you *really* know what you are doing, you may answer\n"
"the next question with yes\n"
"\n"
msgstr ""
"îÅ×ÏÚÍÏÖÎÏ ÕÓÔÁÎÏ×ÉÔØ ÄÏÓÔÏ×ÅÒÎÏ, ÞÔÏ ËÌÀÞ ÐÒÉÎÁÄÌÅÖÉÔ ÔÏÍÕ,\n"
"ËÔÏ ÕËÁÚÁÎ ÅÇÏ ×ÌÁÄÅÌØÃÅÍ. ïÔ×ÅÞÁÊÔÅ \"ÄÁ\" ÎÁ ÓÌÅÄÕÀÝÉÊ ×ÏÐÒÏÓ,\n"
"ÔÏÌØËÏ ÅÓÌÉ ×Ù *ÄÅÊÓÔ×ÉÔÅÌØÎÏ* ÐÏÎÉÍÁÅÔÅ ÞÔÏ ÄÅÌÁÅÔÅ.\n"
-#: g10/pkclist.c:339
+#: g10/pkclist.c:373
msgid "WARNING: Using untrusted key!\n"
msgstr "÷îéíáîéå: éÓÐÏÌØÚÕÅÔÓÑ ËÌÀÞ Ë ËÏÔÏÒÏÍÕ ÎÅÔ ÄÏ×ÅÒÉÑ!\n"
-#: g10/pkclist.c:375
+#: g10/pkclist.c:409
msgid "WARNING: This key has been revoked by its owner!\n"
msgstr "÷îéíáîéå: ÷ÌÁÄÅÌÅà ËÌÀÞÁ ÕÖÅ ÏÔÏÚ×ÁÌ ÅÇÏ!\n"
-#: g10/pkclist.c:376
+#: g10/pkclist.c:410
msgid " This could mean that the signature is forgery.\n"
msgstr " üÔÏ ÍÏÖÅÔ ÏÚÎÁÞÁÔØ, ÞÔÏ ÐÏÄÐÉÓØ ÐÏÄÄÅÌØÎÁÑ.\n"
-#: g10/pkclist.c:397
+#: g10/pkclist.c:431
msgid "Note: This key has expired!\n"
msgstr "úÁÍÅÞÁÎÉÅ: óÒÏË ÄÅÊÓÔ×ÉÑ ËÌÀÞÁ ÕÖÅ ÉÓÔÅË!\n"
-#: g10/pkclist.c:404
+#: g10/pkclist.c:438
msgid "WARNING: This key is not certified with a trusted signature!\n"
msgstr "÷îéíáîéå: üÔÏÔ ËÌÀÞ ÎÅ ÚÁ×ÅÒÅÎ ÄÏ×ÅÒÅÎÎÏÊ ÐÏÄÐÉÓØÀ!\n"
-#: g10/pkclist.c:406
+#: g10/pkclist.c:440
msgid ""
" There is no indication that the signature belongs to the owner.\n"
msgstr ""
" îÅÔ ÎÉËÁËÉÈ ÕËÁÚÁÎÉÑ ÎÁ ÔÏ, ÞÔÏ ËÌÀÞ ÐÒÉÎÁÄÌÅÖÉÔ ÅÇÏ ×ÌÁÄÅÌØÃÕ.\n"
-#: g10/pkclist.c:421
+#: g10/pkclist.c:456
msgid "WARNING: We do NOT trust this key!\n"
msgstr "÷îéíáîéå: íÙ îå ÄÏ×ÅÒÑÅÍ ÜÔÏÍÕ ËÌÀÞÕ!\n"
-#: g10/pkclist.c:422
+#: g10/pkclist.c:457
msgid " The signature is probably a FORGERY.\n"
msgstr " ðÏÄÐÉÓØ ×ÅÒÏÑÔÎÏ -- ðïääåìëá.\n"
-#: g10/pkclist.c:429
+#: g10/pkclist.c:464
msgid ""
"WARNING: This key is not certified with sufficiently trusted signatures!\n"
msgstr "÷îéíáîéå: üÔÏÔ ËÌÀÞ ÎÅ ÚÁ×ÅÒÅÎ ÄÏÓÔÁÔÏÞÎÏ ÄÏ×ÅÒÅÎÎÙÍÉ ÐÏÄÐÉÓÑÍÉ!\n"
-#: g10/pkclist.c:432
+#: g10/pkclist.c:467
msgid " It is not certain that the signature belongs to the owner.\n"
msgstr " îÅÔ Õ×ÅÒÅÎÎÏÓÔÉ, ÞÔÏ ÐÏÄÐÉÓØ ÐÒÉÎÁÄÌÅÖÉÔ ×ÌÁÄÅÌØÃÕ.\n"
-#: g10/pkclist.c:477
+#: g10/pkclist.c:512
msgid ""
"You did not specify a user ID. (you may use \"-r\")\n"
"\n"
msgstr ""
"÷Ù ÎÅ ÕËÁÚÁÌÉ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÏÌØÚÏ×ÁÔÅÌÑ (×ÏÓÐÏÌØÚÕÊÔÅÓØ ÐÁÒÁÍÅÔÒÏÍ "
"\"-r\").\n"
"\n"
-#: g10/pkclist.c:482
+#: g10/pkclist.c:517
msgid "Enter the user ID: "
msgstr "÷×ÅÄÉÔÅ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÏÌØÚÏ×ÁÔÅÌÑ: "
-#: g10/pkclist.c:493
+#: g10/pkclist.c:528
msgid "No such user ID.\n"
msgstr "îÅÔ ÔÁËÏÇÏ ÉÄÅÎÔÉÆÉËÁÔÏÒÁ ÐÏÌØÚÏ×ÁÔÅÌÑ.\n"
-#: g10/pkclist.c:527 g10/pkclist.c:554
+#: g10/pkclist.c:562 g10/pkclist.c:589
#, c-format
msgid "%s: skipped: %s\n"
msgstr "%s: ÐÒÏÐÕÝÅÎ: %s\n"
-#: g10/pkclist.c:535
+#: g10/pkclist.c:570
#, c-format
msgid "%s: error checking key: %s\n"
msgstr "%s: ÏÛÉÂËÁ ÐÒÉ ÐÒÏ×ÅÒËÅ ËÌÀÞÁ: %s\n"
-#: g10/pkclist.c:561
+#: g10/pkclist.c:596
msgid "no valid addressees\n"
msgstr "ÎÅÔ ÄÏÐÕÓÔÉÍÙÈ ÁÄÒÅÓÏ×\n"
#: g10/keygen.c:124
msgid "writing self signature\n"
msgstr "ÐÉÛÅÔÓÑ ÓÁÍÏ-ÐÏÄÐÉÓØ\n"
#: g10/keygen.c:162
msgid "writing key binding signature\n"
msgstr "ÐÉÛÅÔÓÑ \"key-binding\" ÐÏÄÐÉÓØ\n"
#: g10/keygen.c:388
msgid "Please select what kind of key you want:\n"
msgstr "÷ÙÂÅÒÉÔÅ ÖÅÌÁÅÍÙÊ ÔÉÐ ËÌÀÞÁ:\n"
#: g10/keygen.c:390
#, c-format
msgid " (%d) DSA and ElGamal (default)\n"
msgstr " (%d) DSA É ElGamal (ÐÏ ÕÍÏÌÞÁÎÉÀ)\n"
#: g10/keygen.c:391
#, c-format
msgid " (%d) DSA (sign only)\n"
msgstr " (%d) DSA (ÔÏÌØËÏ ÐÏÄÐÉÓØ)\n"
#: g10/keygen.c:393
#, c-format
msgid " (%d) ElGamal (encrypt only)\n"
msgstr " (%d) ElGamal (ÔÏÌØËÏ ÛÉÆÒÏ×ÁÎÉÅ)\n"
#: g10/keygen.c:394
#, c-format
msgid " (%d) ElGamal (sign and encrypt)\n"
msgstr " (%d) ElGamal (ÐÏÄÐÉÓØ É ÛÉÆÒÏ×ÁÎÉÅ)\n"
#: g10/keygen.c:396
#, c-format
msgid " (%d) ElGamal in a v3 packet\n"
msgstr " (%d) ElGamal × v3-ÐÁËÅÔÅ\n"
#: g10/keygen.c:401
msgid "Your selection? "
msgstr "÷ÁÛ ×ÙÂÏÒ? "
#: g10/keygen.c:411
#, fuzzy
msgid "Do you really want to create a sign and encrypt key? "
msgstr "÷Ù ÄÅÊÓÔ×ÉÔÅÌØÎÏ ÈÏÔÉÔÅ ÕÄÁÌÉÔØ ×ÙÂÒÁÎÎÙÅ ËÌÀÞÉ? "
#: g10/keygen.c:432
msgid "Invalid selection.\n"
msgstr "îÅÄÏÐÕÓÔÉÍÙÊ ×ÙÂÏÒ.\n"
#: g10/keygen.c:444
#, c-format
msgid ""
"About to generate a new %s keypair.\n"
" minimum keysize is 768 bits\n"
" default keysize is 1024 bits\n"
" highest suggested keysize is 2048 bits\n"
msgstr ""
"óÏÂÉÒÁÅÍÓÑ ÓÇÅÎÅÒÉÒÏ×ÁÔØ %s ËÌÀÞÅ×ÕÀ ÐÁÒÕ.\n"
" ÍÉÎÉÍÁÌØÎÁÑ ÄÌÉÎÁ ËÌÀÞÁ: 768 ÂÉÔ\n"
" ÄÌÉÎÁ ËÌÀÞÁ ÐÏ ÕÍÏÌÞÁÎÉÀ: 1024 ÂÉÔÁ\n"
" ÍÁËÓÉÍÁÌØÎÁÑ ÒÅËÏÍÅÎÄÕÅÍÁÑ ÄÌÉÎÁ ËÌÀÞÁ: 2048 ÂÉÔ\n"
#: g10/keygen.c:451
msgid "What keysize do you want? (1024) "
msgstr "ëÁËÏÇÏ ÒÁÚÍÅÒÁ ËÌÀÞ ×Ù ÖÅÌÁÅÔÅ? (1024)"
#: g10/keygen.c:456
msgid "DSA only allows keysizes from 512 to 1024\n"
msgstr "äÏÐÕÓÔÉÍÙÊ ÒÁÚÍÅÒ DSA ËÌÀÞÅÊ - ÏÔ 512 ÄÏ 1024 ÂÉÔ\n"
#: g10/keygen.c:458
msgid "keysize too small; 768 is smallest value allowed.\n"
msgstr "ÓÌÉÛËÏÍ ÍÁÌÅÎØËÁÑ ÄÌÉÎÁ ËÌÀÞÁ, ÎÁÉÍÅÎØÛÅÅ ÚÎÁÞÅÎÉÅ - 768.\n"
#: g10/keygen.c:461
#, fuzzy
msgid ""
"Keysizes larger than 2048 are not suggested because\n"
"computations take REALLY long!\n"
msgstr ""
"ëÌÀÞÉ ÄÌÉÎÏÊ ÂÏÌØÛÅ 2048 ÎÅ ÒÅËÏÍÅÎÄÕÀÔÓÑ, ÐÏÔÏÍÕ ÞÔÏ ×ÙÞÉÓÌÅÎÉÑÚÁÎÉÍÁÀÔ "
"ïþåîø ÍÎÏÇÏ ×ÒÅÍÅÎÉ!\n"
#: g10/keygen.c:464
msgid "Are you sure that you want this keysize? "
msgstr "÷Ù ÄÅÊÓÔ×ÉÔÅÌØÎÏ ÈÏÔÉÔÅ ËÌÀÞ ÔÁËÏÊ ÄÌÉÎÙ? "
#: g10/keygen.c:465
msgid ""
"Okay, but keep in mind that your monitor and keyboard radiation is also very "
"vulnerable to attacks!\n"
msgstr ""
"ïË, ÔÏÌØËÏ ÎÅ ÚÁÂÙ×ÁÊÔÅ, ÞÔÏ ÉÚÌÕÞÅÎÉÅ ×ÁÛÉÈ ËÌÁ×ÉÁÔÕÒÙ É ÍÏÎÉÔÏÒÁ ÔÏÖÅ\n"
"ÄÅÌÁÀÔ ×ÁÓ ÕÑÚ×ÉÍÙÍ ÄÌÑ ÁÔÁË.\n"
#: g10/keygen.c:473
msgid "Do you really need such a large keysize? "
msgstr "÷ÁÍ ÄÅÊÓÔ×ÉÔÅÌØÎÏ ÎÕÖÅÎ ÔÁËÏÊ ÄÌÉÎÎÙÊ ËÌÀÞ? "
#: g10/keygen.c:479
#, c-format
msgid "Requested keysize is %u bits\n"
msgstr "úÁÐÒÏÛÅÎÎÙÊ ËÌÀÞ ÉÍÅÅÔ ÄÌÉÎÕ %u ÂÉÔ\n"
#: g10/keygen.c:482 g10/keygen.c:486
#, c-format
msgid "rounded up to %u bits\n"
msgstr "ÏËÒÕÇÌÅÎÏ ÄÏ %u ÂÉÔ\n"
#: g10/keygen.c:499
msgid ""
"Please specify how long the key should be valid.\n"
" 0 = key does not expire\n"
" <n> = key expires in n days\n"
" <n>w = key expires in n weeks\n"
" <n>m = key expires in n months\n"
" <n>y = key expires in n years\n"
msgstr ""
"ðÏÖÁÌÕÊÓÔÁ, ÕËÁÖÉÔÅ ÐÒÏÄÏÌÖÉÔÅÌØÎÏÓÔØ ÄÅÊÓÔ×ÉÑ ×ÁÛÅÇÏ ËÌÀÞÁ.\n"
" 0 = ÂÅÓÓÒÏÞÎÙÊ ËÌÀÞ\n"
" <n> = ÓÒÏË ÄÅÊÓÔ×ÉÑ ËÌÀÞÁ n ÄÎÅÊ\n"
" <n>w = ÓÒÏË ÄÅÊÓÔ×ÉÑ ËÌÀÞÁ n ÎÅÄÅÌØ\n"
" <n>m = ÓÒÏË ÄÅÊÓÔ×ÉÑ ËÌÀÞÁ n ÍÅÓÑÃÅ×\n"
" <n>y = ÓÒÏË ÄÅÊÓÔ×ÉÑ ËÌÀÞÁ n ÌÅÔ\n"
#: g10/keygen.c:514
msgid "Key is valid for? (0) "
msgstr "ëÌÀÞ ÄÅÊÓÔ×ÉÔÅÌÅÎ × ÔÅÞÅÎÉÅ? (0) "
#: g10/keygen.c:525
msgid "invalid value\n"
msgstr "ÎÅÄÏÐÕÓÔÉÍÏÅ ÚÎÁÞÅÎÉÅ.\n"
#: g10/keygen.c:530
msgid "Key does not expire at all\n"
msgstr "âÅÓÓÒÏÞÎÙÊ ËÌÀÞ.\n"
#. print the date when the key expires
#: g10/keygen.c:536
#, c-format
msgid "Key expires at %s\n"
msgstr "ëÌÀÞ ÄÅÊÓÔ×ÕÅÔ ÄÏ %s\n"
#: g10/keygen.c:542
msgid "Is this correct (y/n)? "
msgstr "üÔÏ ×ÅÒÎÏ? (y/n) "
#: g10/keygen.c:584
msgid ""
"\n"
"You need a User-ID to identify your key; the software constructs the user "
"id\n"
"from Real Name, Comment and Email Address in this form:\n"
" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n"
"\n"
msgstr ""
"\n"
"äÌÑ ÉÄÅÎÔÉÆÉËÁÃÉÉ ËÌÀÞÁ ÎÅÏÂÈÏÄÉÍ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÏÌØÚÏ×ÁÔÅÌÑ; ÐÒÏÇÒÁÍÍÁ\n"
"ËÏÎÓÔÒÕÉÒÕÅÔ ÅÇÏ ÉÚ ÐÏÌÎÏÇÏ ÉÍÅÎÉ ÐÏÌØÚÏ×ÁÔÅÌÑ, ËÏÍÍÅÎÔÁÒÉÑ É ÁÄÒÅÓÁ email× "
"×ÉÄÅ:\n"
" \"Vasya Pupkin (KRUTOI) <vasya@mega-cool.ru>\"\n"
"\n"
#: g10/keygen.c:595
msgid "Real name: "
msgstr "÷ÁÛÅ ÉÍÑ (\"éÍÑ æÁÍÉÌÉÑ\"): "
#: g10/keygen.c:599
msgid "Invalid character in name\n"
msgstr "îÅÄÏÐÕÓÔÉÍÙÊ ÓÉÍ×ÏÌ × ÉÍÅÎÉ\n"
#: g10/keygen.c:601
msgid "Name may not start with a digit\n"
msgstr "ðÏÌÎÏÅ ÉÍÑ ÎÅ ÍÏÖÅÔ ÎÁÞÉÎÁÔØÓÑ Ó ÃÉÆÒÙ.\n"
#: g10/keygen.c:603
msgid "Name must be at least 5 characters long\n"
msgstr "ðÏÌÎÏÅ ÉÍÑ ÄÏÌÖÎÏ ÓÏÓÔÏÑÔØ ÎÅ ÍÅÎÅÅ ÞÅÍ ÉÚ 5ÔÉ ÓÉÍ×ÏÌÏ×.\n"
#: g10/keygen.c:611
msgid "Email address: "
msgstr "E-Mail: "
#: g10/keygen.c:623
msgid "Not a valid email address\n"
msgstr "îÅÄÏÐÕÓÔÉÍÙÊ E-Mail\n"
#: g10/keygen.c:631
msgid "Comment: "
msgstr "ëÏÍÍÅÎÔÁÒÉÊ: "
#: g10/keygen.c:637
msgid "Invalid character in comment\n"
msgstr "îÅÄÏÐÕÓÔÉÍÙÊ ÓÉÍ×ÏÌ × ËÏÍÍÅÎÔÁÒÉÉ.\n"
#: g10/keygen.c:657
#, c-format
msgid ""
"You selected this USER-ID:\n"
" \"%s\"\n"
"\n"
msgstr ""
"÷Ù ×ÙÂÒÁÌÉ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÏÌØÚÏ×ÁÔÅÌÑ:\n"
" \"%s\"\n"
"\n"
#: g10/keygen.c:660
msgid "NnCcEeOoQq"
msgstr ""
#: g10/keygen.c:670
#, fuzzy
msgid "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? "
msgstr "éÚÍÅÎÉÔØ: N=éÍÑ, C=ëÏÍÍÅÎÔÁÒÉÊ, E=E-Mail, O=Okay/Q=÷ÙÈÏÄ? "
#: g10/keygen.c:722
msgid ""
"You need a Passphrase to protect your secret key.\n"
"\n"
msgstr ""
"äÌÑ ÚÁÝÉÔÙ ×ÁÛÅÇÏ ËÌÀÞÁ ÎÕÖÎÁ ËÌÀÞÅ×ÁÑ ÆÒÁÚÁ.\n"
"\n"
#: g10/keyedit.c:389 g10/keygen.c:730
msgid "passphrase not correctly repeated; try again.\n"
msgstr "ËÌÀÞÅ×ÁÑ ÆÒÁÚÁ ÎÅ ÂÙÌÁ ×ÏÓÐÒÏÉÚ×ÅÄÅÎÁ, ÐÏÐÒÏÂÕÊÔÅ ÓÎÏ×Á.\n"
#: g10/keygen.c:736
msgid ""
"You don't want a passphrase - this is probably a *bad* idea!\n"
"I will do it anyway. You can change your passphrase at any time,\n"
"using this program with the option \"--edit-key\".\n"
"\n"
msgstr ""
"÷Ù ÎÅ ÈÏÔÉÔÅ ÉÓÐÏÌØÚÏ×ÁÔØ ËÌÀÞÅ×ÕÀ ÆÒÁÚÕ - ÜÔÏ, ÓËÏÒÅÅ ×ÓÅÇÏ, *ÐÌÏÈÁÑ*\n"
"ÉÄÅÑ. îÏ Ñ ÓÄÅÌÁÀ, ÞÔÏ ÷Ù ÈÏÔÉÔÅ. ëÌÀÞÅ×ÕÀ ÆÒÁÚÕ ÍÏÖÎÏ ÓÍÅÎÉÔØ × ÌÀÂÏÅ\n"
"×ÒÅÍÑ, ÚÁÐÕÓÔÉ× ÜÔÕ ÐÒÏÇÒÁÍÍÕ Ó ÐÁÒÁÍÅÔÒÏÍ \"--edit-key\".\n"
"\n"
#: g10/keygen.c:757
msgid ""
"We need to generate a lot of random bytes. It is a good idea to perform\n"
"some other action (work in another window, move the mouse, utilize the\n"
"network and the disks) during the prime generation; this gives the random\n"
"number generator a better chance to gain enough entropy.\n"
msgstr ""
"îÁÍ ÎÕÖÎÏ ÓÇÅÎÅÒÉÒÏ×ÁÔØ ÍÎÏÇÏ ÓÌÕÞÁÊÎÙÈ ÂÁÊÔÏ×. óÅÊÞÁÓ ÏÞÅÎØ ÈÏÒÏÛÏ ÂÙÌÏ ÂÙ\n"
"ÞÔÏ-ÔÏ ÐÏÄÅÌÁÔØ ÎÁ ÍÁÛÉÎÅ (ÐÏÒÁÂÏÔÁÔØ × ÄÒÕÇÏÍ ÏËÎÅ, ÐÏÄ×ÉÇÁÔØ ÍÙÛØ,\n"
"ÎÁÇÒÕÚÉÔØ ÓÅÔÅ×ÕÀ ÉÌÉ ÄÉÓËÏ×ÕÀ ÐÏÄÓÉÓÔÅÍÕ). üÔÏ ÄÁÓÔ ÇÅÎÅÒÁÔÏÒÕ ÓÌÕÞÁÊÎÙÈ\n"
"ÞÉÓÅÌ ×ÏÚÍÏÖÎÏÓÔØ ÎÁÂÒÁÔØ ÄÏÓÔÁÔÏÞÎÏ ÜÎÔÒÏÐÉÉ.\n"
#: g10/keygen.c:827
msgid "Key generation can only be used in interactive mode\n"
msgstr "çÅÎÅÒÁÃÉÑ ËÌÀÞÁ ÍÏÖÅÔ ÂÙÔØ ×ÙÐÏÌÎÅÎÁ ÔÏÌØËÏ × ÉÎÔÅÒÁËÔÉ×ÎÏÍ ÒÅÖÉÍÅ.\n"
#: g10/keygen.c:835
msgid "DSA keypair will have 1024 bits.\n"
msgstr "ëÌÀÞÅ×ÁÑ ÐÁÒÁ DSA ÂÕÄÅÔ ÉÍÅÔØ ÄÌÉÎÕ 1024 ÂÉÔÁ.\n"
#: g10/keygen.c:841
#, fuzzy
msgid "Key generation cancelled.\n"
msgstr "çÅÎÅÒÁÃÉÑ ËÌÀÞÁ ÏÔÍÅÎÅÎÁ: %s\n"
#: g10/keygen.c:851
#, c-format
msgid "writing public certificate to '%s'\n"
msgstr "ÏÔËÒÙÔÙÊ ÓÅÒÔÉÆÉËÁÔ ÚÁÐÉÓÙ×ÁÅÔÓÑ × '%s'\n"
#: g10/keygen.c:852
#, c-format
msgid "writing secret certificate to '%s'\n"
msgstr "ÓÅËÒÅÔÎÙÊ ÓÅÒÔÉÆÉËÁÔ ÚÁÐÉÓÙ×ÁÅÔÓÑ × '%s'\n"
#: g10/keygen.c:929
msgid "public and secret key created and signed.\n"
msgstr "ÏÔËÒÙÔÙÊ É ÓÅËÒÅÔÎÙÊ ËÌÀÞÉ ÓÏÚÄÁÎÙ É ÐÏÄÐÉÓÁÎÙ.\n"
#: g10/keygen.c:931
msgid ""
"Note that this key cannot be used for encryption. You may want to use\n"
"the command \"--add-key\" to generate a secondary key for this purpose.\n"
msgstr ""
"ïÂÒÁÔÉÔÅ ×ÎÉÍÁÎÉÅ, ÞÔÏ ÜÔÏÔ ËÌÀÞ ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÓÐÏÌØÚÏ×ÁÎ ÄÌÑ ÛÉÆÒÏ×ÁÎÉÑ.\n"
"÷Ù ÍÏÖÅÔÅ ×ÏÓÐÏÌØÚÏ×ÁÔØÓÑ ÐÁÒÁÍÅÔÒÏÍ --add-key ÄÌÑ ÇÅÎÅÒÁÃÉÉ "
"ÄÏÐÏÌÎÉÔÅÌØÎÏÇÏ\n"
"ËÌÀÞÁ ÄÌÑ ÛÉÆÒÏ×ÁÎÉÑ.\n"
#: g10/keygen.c:945 g10/keygen.c:1030
#, c-format
msgid "Key generation failed: %s\n"
msgstr "çÅÎÅÒÁÃÉÑ ËÌÀÞÁ ÎÅ ÕÄÁÌÁÓØ: %s\n"
#: g10/keygen.c:1008
#, fuzzy
msgid "Really create? "
msgstr "äÅÊÓÔ×ÉÔÅÌØÎÏ ÓÏÚÄÁÔØ? "
#: g10/encode.c:88 g10/openfile.c:81 g10/openfile.c:158 g10/tdbio.c:445
#: g10/tdbio.c:504
#, c-format
msgid "%s: can't open: %s\n"
msgstr "%s: ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ: %s\n"
#: g10/encode.c:107
#, c-format
msgid "error creating passphrase: %s\n"
msgstr "ÏÛÉÂËÁ ÐÒÉ ÓÏÚÄÁÎÉÉ ËÌÀÞÅ×ÏÊ ÆÒÁÚÙ: %s\n"
#: g10/encode.c:155 g10/encode.c:269
#, fuzzy, c-format
msgid "%s: WARNING: empty file\n"
msgstr "%s: ÐÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÐÕÓÔÏÊ ÆÁÊÌ.\n"
#: g10/encode.c:222
#, c-format
msgid "reading from '%s'\n"
msgstr "þÉÔÁÅÔÓÑ ÉÚ '%s'\n"
#: g10/encode.c:397
#, fuzzy, c-format
msgid "%s/%s encrypted for: %s\n"
msgstr "%s ÚÁÛÉÆÒÏ×ÁÎÏ ÄÌÑ: %s\n"
#: g10/export.c:114
#, fuzzy, c-format
msgid "%s: user not found: %s\n"
msgstr "%s: ÐÏÌØÚÏ×ÁÔÅÌØ ÎÅ ÎÁÊÄÅÎ\n"
#: g10/export.c:123
#, c-format
msgid "certificate read problem: %s\n"
msgstr ""
#: g10/export.c:132
#, fuzzy, c-format
msgid "key %08lX: not a rfc2440 key - skipped\n"
msgstr "ÓÅËÒÅÔÎÙÊ ËÌÀÞ %08lX: ÎÅ ÉÍÅÅÔ ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÅÇÏ ÏÔËÒÙÔÏÇÏ ËÌÀÞÁ.\n"
#: g10/export.c:174
#, fuzzy
msgid "WARNING: nothing exported\n"
msgstr "÷îéíáîéå: éÓÐÏÌØÚÕÅÔÓÑ ËÌÀÞ Ë ËÏÔÏÒÏÍÕ ÎÅÔ ÄÏ×ÅÒÉÑ!\n"
#: g10/getkey.c:164
msgid "too many entries in pk cache - disabled\n"
msgstr ""
#: g10/getkey.c:263
msgid "too many entries in unk cache - disabled\n"
msgstr ""
#: g10/getkey.c:989
#, c-format
msgid "using secondary key %08lX instead of primary key %08lX\n"
msgstr "ÉÓÐÏÌØÚÕÅÔÓÑ ÄÏÐÏÌÎÉÔÅÌØÎÙÊ ËÌÀÞ %09lX ×ÍÅÓÔÏ ÏÓÎÏ×ÎÏÇÏ %08lX%\n"
-#: g10/import.c:129 g10/trustdb.c:1166
+#: g10/import.c:129 g10/trustdb.c:1180
#, c-format
msgid "can't open file: %s\n"
msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ: %s\n"
#: g10/import.c:145
#, c-format
msgid "skipping block of type %d\n"
msgstr "ÐÒÏÐÕÓËÁÅÍ ÂÌÏË ÔÉÐÁ %d\n"
-#: g10/import.c:152 g10/trustdb.c:1425 g10/trustdb.c:1494
+#: g10/import.c:152 g10/trustdb.c:1474 g10/trustdb.c:1543
#, c-format
msgid "%lu keys so far processed\n"
msgstr ""
-#: g10/import.c:157 g10/trustdb.c:1242
+#: g10/import.c:157 g10/trustdb.c:1256
#, c-format
msgid "read error: %s\n"
msgstr "ÏÛÉÂËÁ ÞÔÅÎÉÑ: %s\n"
#: g10/import.c:159
#, c-format
msgid "Total number processed: %lu\n"
msgstr ""
#: g10/import.c:161
#, c-format
msgid " w/o user IDs: %lu\n"
msgstr ""
#: g10/import.c:163
#, c-format
msgid " imported: %lu"
msgstr ""
#: g10/import.c:169
#, c-format
msgid " unchanged: %lu\n"
msgstr ""
#: g10/import.c:171
#, c-format
msgid " new user IDs: %lu\n"
msgstr ""
#: g10/import.c:173
#, c-format
msgid " new subkeys: %lu\n"
msgstr ""
#: g10/import.c:175
#, fuzzy, c-format
msgid " new signatures: %lu\n"
msgstr "ËÌÀÞ %08lX: %d ÎÏ×ÙÈ ÐÏÄÐÉÓÅÊ\n"
#: g10/import.c:177
#, c-format
msgid " new key revocations: %lu\n"
msgstr ""
#: g10/import.c:179
#, c-format
msgid " secret keys read: %lu\n"
msgstr ""
#: g10/import.c:181
#, fuzzy, c-format
msgid " secret keys imported: %lu\n"
msgstr "ËÌÀÞ %08lX: ÓÅËÒÅÔÎÙÊ ËÌÀÞ ÉÍÐÏÒÔÉÒÏ×ÁÎ\n"
#: g10/import.c:183
#, fuzzy, c-format
msgid " secret keys unchanged: %lu\n"
msgstr "éÓÐÏÌØÚÏ×ÁÎ ÎÅÐÒÁ×ÉÌØÎÙÊ ÓÅËÒÅÔÎÙÊ ËÌÀÞ"
#: g10/import.c:325 g10/import.c:517
#, c-format
msgid "key %08lX: no user id\n"
msgstr "ËÌÀÞ %08lX: ÎÅÔ ÉÄÅÎÔÉÆÉËÁÔÏÒÁ ÐÏÌØÚÏ×ÁÔÅÌÑ\n"
#: g10/import.c:336
#, c-format
msgid "key %08lX: no valid user ids\n"
msgstr "ËÌÀÞ %08lX: ÎÅÔ ÄÏÐÕÓÔÉÍÙÈ ÉÄÅÎÔÉÆÉËÁÔÏÒÏ× ÐÏÌØÚÏ×ÁÔÅÌÅÊ\n"
#: g10/import.c:338
msgid "this may be caused by a missing self-signature\n"
msgstr "ÜÔÏ ÍÏÖÅÔ ÂÙÔØ ×ÙÚ×ÁÎÏ ÏÔÓÕÔÓÔ×ÉÅÍ ÓÁÍÏ-ÐÏÄÐÉÓÉ\n"
#: g10/import.c:349 g10/import.c:585
#, c-format
msgid "key %08lX: public key not found: %s\n"
msgstr "ËÌÀÞ %08lX: ÏÔËÒÙÔÙÊ ËÌÀÞ ÎÅ ÎÁÊÄÅÎ: %s\n"
#: g10/import.c:355
msgid "no default public keyring\n"
msgstr "ÎÅÔ Ó×ÑÚËÉ ÏÔËÒÙÔÙÈ ËÌÀÞÅÊ ÐÏ ÕÍÏÌÞÁÎÉÀ\n"
-#: g10/import.c:359 g10/openfile.c:105 g10/sign.c:205 g10/sign.c:569
+#: g10/import.c:359 g10/openfile.c:105 g10/sign.c:205 g10/sign.c:592
#, c-format
msgid "writing to '%s'\n"
msgstr "ÚÁÐÉÓÙ×ÁÅÔÓÑ × '%s'\n"
#: g10/import.c:363 g10/import.c:423 g10/import.c:639
#, c-format
msgid "can't lock public keyring: %s\n"
msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÚÁÂÌÏËÉÒÏ×ÁÔØ Ó×ÑÚËÕ ÏÔËÒÙÔÙÈ ËÌÀÞÅÊ: %s\n"
#: g10/import.c:366
#, c-format
msgid "can't write to keyring: %s\n"
msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÚÁÐÉÓÁÔØ × Ó×ÑÚËÕ ËÌÀÞÅÊ: %s\n"
#: g10/import.c:370
#, c-format
msgid "key %08lX: public key imported\n"
msgstr "ËÌÀÞ %08lX: ÏÔËÒÙÔÙÊ ËÌÀÞ ÉÍÐÏÒÔÉÒÏ×ÁÎ\n"
#: g10/import.c:383
#, c-format
msgid "key %08lX: doesn't match our copy\n"
msgstr "ËÌÀÞ %08lX: ÎÅ ÓÏ×ÐÁÄÁÅÔ Ó ÎÁÛÅÊ ËÏÐÉÅÊ\n"
#: g10/import.c:396 g10/import.c:594
#, c-format
msgid "key %08lX: can't locate original keyblock: %s\n"
msgstr "ËÌÀÞ %08lX: ÎÅ×ÏÚÍÏÖÎÏ ÏÂÎÁÒÕÖÉÔØ original keyblock: %s\n"
#: g10/import.c:403 g10/import.c:601
#, c-format
msgid "key %08lX: can't read original keyblock: %s\n"
msgstr "ËÌÀÞ %08lX: ÎÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ original keyblock: %s\n"
#: g10/import.c:420 g10/import.c:532 g10/import.c:636
msgid "writing keyblock\n"
msgstr "ÚÁÐÉÓÙ×ÁÅÔÓÑ ÂÌÏË ËÌÀÞÁ\n"
#: g10/import.c:426 g10/import.c:642
#, c-format
msgid "can't write keyblock: %s\n"
msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÚÁÐÉÓÁÔØ ÂÌÏË ËÌÀÞÁ: %s\n"
#: g10/import.c:431
#, c-format
msgid "key %08lX: 1 new user-id\n"
msgstr "ËÌÀÞ %08lX: 1 ÎÏ×ÙÊ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÏÌØÚÏ×ÁÔÅÌÑ\n"
#: g10/import.c:434
#, c-format
msgid "key %08lX: %d new user-ids\n"
msgstr "ËÌÀÞ %08lX: %d ÎÏ×ÙÈ ÉÄÅÎÔÉÆÉËÁÔÏÒÏ× ÐÏÌØÚÏ×ÁÔÅÌÅÊ\n"
#: g10/import.c:437
#, c-format
msgid "key %08lX: 1 new signature\n"
msgstr "ËÌÀÞ %08lX: 1 ÎÏ×ÁÑ ÐÏÄÐÉÓØ\n"
#: g10/import.c:440
#, c-format
msgid "key %08lX: %d new signatures\n"
msgstr "ËÌÀÞ %08lX: %d ÎÏ×ÙÈ ÐÏÄÐÉÓÅÊ\n"
#: g10/import.c:443
#, c-format
msgid "key %08lX: 1 new subkey\n"
msgstr "ËÌÀÞ %08lX: 1 ÎÏ×ÙÊ ÐÏÄ-ËÌÀÞ\n"
#: g10/import.c:446
#, c-format
msgid "key %08lX: %d new subkeys\n"
msgstr "ËÌÀÞ %08lX: %d ÎÏ×ÙÈ ÐÏÄ-ËÌÀÞÅÊ\n"
#: g10/import.c:456
#, c-format
msgid "key %08lX: not changed\n"
msgstr "ËÌÀÞ %08lX: ÎÅ ÉÚÍÅÎÅÎ\n"
#: g10/import.c:535
#, c-format
msgid "can't lock secret keyring: %s\n"
msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÚÁÂÌÏËÉÒÏ×ÁÔØ Ó×ÑÚËÕ ÓÅËÒÅÔÎÙÈ ËÌÀÞÅÊ: %s\n"
#: g10/import.c:538
#, fuzzy, c-format
msgid "can't write keyring: %s\n"
msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÚÁÐÉÓÁÔØ Ó×ÑÚËÕ ËÌÀÞÅÊ: %s\n"
#. we are ready
#: g10/import.c:541
#, c-format
msgid "key %08lX: secret key imported\n"
msgstr "ËÌÀÞ %08lX: ÓÅËÒÅÔÎÙÊ ËÌÀÞ ÉÍÐÏÒÔÉÒÏ×ÁÎ\n"
#. we can't merge secret keys
#: g10/import.c:545
#, c-format
msgid "key %08lX: already in secret keyring\n"
msgstr "ËÌÀÞ %08lX: ÕÖÅ ÎÁ Ó×ÑÚËÅ ÓÅËÒÅÔÎÙÈ ËÌÀÞÅÊ\n"
#: g10/import.c:550
#, c-format
msgid "key %08lX: secret key not found: %s\n"
msgstr "ËÌÀÞ %08lX: ÓÅËÒÅÔÎÙÊ ËÌÀÞ ÎÅ ÎÁÊÄÅÎ: %s\n"
#: g10/import.c:579
#, c-format
msgid "key %08lX: no public key - can't apply revocation certificate\n"
msgstr ""
"ËÌÀÞ %08lX: ÎÅÔ ÏÔËÒÙÔÏÇÏ ËÌÀÞÁ - ÎÅ×ÏÚÍÏÖÎÏ ÐÒÉÍÅÎÉÔØ ÏÔÚÙ×ÁÀÝÉÊ "
"ÓÅÒÔÉÆÉËÁÔ\n"
#: g10/import.c:612
#, c-format
msgid "key %08lX: invalid revocation certificate: %s - rejected\n"
msgstr "ËÌÀÞ %08lX: ÎÅÄÏÐÕÓÔÉÍÙÊ ÏÔÚÙ×ÁÀÝÉÊ ÓÅÒÔÉÆÉËÁÔ: %s - ÏÔ×ÅÒÇÎÕÔ\n"
#: g10/import.c:646
#, c-format
msgid "key %08lX: revocation certificate imported\n"
msgstr "ËÌÀÞ %08lX: ÏÔÚÙ×ÁÀÝÉÊ ÓÅÒÔÉÆÉËÁÔ ÉÍÐÏÒÔÉÒÏ×ÁÎ\n"
#: g10/import.c:677
#, c-format
msgid "key %08lX: no user-id for signature\n"
msgstr "ËÌÀÞ %08lX: ÎÅÔ ÉÄÅÎÔÉÆÉËÁÔÏÒÁ ÐÏÌØÚÏ×ÁÔÅÌÑ ÄÌÑ ÐÏÄÐÉÓÉ\n"
#: g10/import.c:684
#, c-format
msgid "key %08lX: unsupported public key algorithm\n"
msgstr "ËÌÀÞ %08lX: ÎÅÐÏÄÄÅÒÖÉ×ÁÅÍÙÊ ÁÌÇÏÒÉÔÍ ÏÔËÒÙÔÏÇÏ ËÌÀÞÁ\n"
#: g10/import.c:685
#, c-format
msgid "key %08lX: invalid self-signature\n"
msgstr "ËÌÀÞ %08lX: ÎÅÄÏÐÕÓÔÉÍÁÑ ÓÁÍÏ-ÐÏÄÐÉÓØ\n"
#: g10/import.c:714
#, c-format
msgid "key %08lX: skipped userid '"
msgstr "ËÌÀÞ %08lX: ÐÒÏÐÕÝÅÎ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÏÌØÚÏ×ÁÔÅÌÑ '"
#: g10/import.c:737
#, c-format
msgid "key %08lX: revocation certificate at wrong place - skipped\n"
msgstr "ËÌÀÞ %08lX: ÏÔÚÙ×ÁÀÝÉÊ ÓÅÒÔÉÆÉËÁÔ × ÎÅÐÒÁ×ÉÌØÎÏÍ ÍÅÓÔÅ - ÐÒÏÐÕÝÅÎ\n"
#: g10/import.c:745
#, c-format
msgid "key %08lX: invalid revocation certificate: %s - skipped\n"
msgstr "ËÌÀÞ %08lX: ÎÅÄÏÐÕÓÔÉÍÙÊ ÏÔÚÙ×ÁÀÝÉÊ ÓÅÒÔÉÆÉËÁÔ: %s - ÐÒÏÐÕÝÅÎ\n"
#: g10/import.c:804
#, c-format
msgid "key %08lX: revocation certificate added\n"
msgstr "ËÌÀÞ %08lX: ÏÔÚÙ×ÁÀÝÉÊ ÓÅÒÔÉÆÉËÁÔ ÄÏÂÁ×ÌÅÎ\n"
#: g10/import.c:918 g10/import.c:973
#, c-format
msgid "key %08lX: our copy has no self-signature\n"
msgstr "ËÌÀÞ %08lX: ÎÁÛÁ ËÏÐÉÑ ÎÅ ÉÍÅÅÔ ÓÁÍÏ-ÐÏÄÐÉÓÉ\n"
#: g10/keyedit.c:81
#, c-format
msgid "%s: user not found\n"
msgstr "%s: ÐÏÌØÚÏ×ÁÔÅÌØ ÎÅ ÎÁÊÄÅÎ\n"
#: g10/keyedit.c:164
#, fuzzy
msgid "[self-signature]"
msgstr "[ÓÁÍÏ-ÐÏÄÐÉÓØ]\n"
#: g10/keyedit.c:182
#, fuzzy
msgid "1 bad signature\n"
msgstr "1 ÐÌÏÈÁÑ ÐÏÄÐÉÓØ\n"
#: g10/keyedit.c:184
#, c-format
msgid "%d bad signatures\n"
msgstr "%d ÐÌÏÈÉÈ ÐÏÄÐÉÓÅÊ\n"
#: g10/keyedit.c:186
#, fuzzy
msgid "1 signature not checked due to a missing key\n"
msgstr "1 ÐÏÄÐÉÓØ ÎÅ ÐÒÏ×ÅÒÅÎÁ ÉÚ-ÚÁ ÏÔÓÕÔÓÔ×ÉÑ ËÌÀÞÁ\n"
#: g10/keyedit.c:188
#, fuzzy, c-format
msgid "%d signatures not checked due to missing keys\n"
msgstr "%s ÐÏÄÐÉÓÅÊ ÎÅ ÐÒÏ×ÅÒÅÎÏ ÉÚ-ÚÁ ÏÔÓÕÔÓÔ×ÉÑ ËÌÀÞÅÊ\n"
#: g10/keyedit.c:190
#, fuzzy
msgid "1 signature not checked due to an error\n"
msgstr "1 ÐÏÄÐÉÓØ ÎÅ ÐÒÏ×ÅÒÅÎÁ ÉÚ-ÚÁ ÏÛÉÂËÉ\n"
#: g10/keyedit.c:192
#, c-format
msgid "%d signatures not checked due to errors\n"
msgstr "%s ÐÏÄÐÉÓÅÊ ÎÅ ÐÒÏ×ÅÒÅÎÏ ÉÚ-ÚÁ ÏÛÉÂÏË\n"
#: g10/keyedit.c:194
#, fuzzy
msgid "1 user id without valid self-signature detected\n"
msgstr "ÏÂÎÁÒÕÖÅÎ 1 ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÏÌØÚÏ×ÁÔÅÌÑ ÂÅÚ ÄÏÐÕÓÔÉÍÏÊ ÓÁÍÏ-ÐÏÄÐÉÓÉ\n"
#: g10/keyedit.c:196
#, c-format
msgid "%d user ids without valid self-signatures detected\n"
msgstr ""
"ÏÂÎÁÒÕÖÅÎÏ %d ÉÄÅÎÔÉÆÉËÁÔÏÒÏ× ÐÏÌØÚÏ×ÁÔÅÌÅÊ ÂÅÚ ÄÏÐÕÓÔÉÍÙÈ ÓÁÍÏ-ÐÏÄÐÉÓÅÊ\n"
#: g10/keyedit.c:258
#, fuzzy, c-format
msgid "Already signed by key %08lX\n"
msgstr "õÖÅ ÐÏÄÐÉÓÁÎÏ ËÌÀÞÏÍ %08lX.\n"
#: g10/keyedit.c:266
#, fuzzy, c-format
msgid "Nothing to sign with key %08lX\n"
msgstr "îÅÞÅÇÏ ÐÏÄÐÉÓÙ×ÁÔØ ËÌÀÞÁÍ %08lX\n"
#: g10/keyedit.c:275
#, fuzzy
msgid ""
"Are you really sure that you want to sign this key\n"
"with your key: \""
msgstr "÷Ù ÄÅÊÓÔ×ÉÔÅÌØÎÏ Õ×ÅÒÅÎÙ, ÞÔÏ ÈÏÔÉÔÅ ÐÏÄÐÉÓÁÔØ ÜÔÏÔ ËÌÀÞ Ó×ÏÉÍ:\n"
#: g10/keyedit.c:282
msgid "Really sign? "
msgstr "äÅÊÓÔ×ÉÔÅÌØÎÏ ÐÏÄÐÉÓÁÔØ? "
#: g10/keyedit.c:303 g10/sign.c:65
#, fuzzy, c-format
msgid "signing failed: %s\n"
msgstr "ÏÛÉÂËÁ ÐÏÄÐÉÓÙ×ÁÎÉÑ: %s\n"
#: g10/keyedit.c:356
msgid "This key is not protected.\n"
msgstr "üÔÏÔ ËÌÀÞ ÎÅ ÚÁÝÉÝÅÎ.\n"
#: g10/keyedit.c:359
msgid "Key is protected.\n"
msgstr "üÔÏÔ ËÌÀÞ ÚÁÝÉÝÅÎ.\n"
#: g10/keyedit.c:376
#, c-format
msgid "Can't edit this key: %s\n"
msgstr "îÅ×ÏÚÍÏÖÎÏ ÒÅÄÁËÔÉÒÏ×ÁÔØ ÜÔÏÔ ËÌÀÞ: %s\n"
#: g10/keyedit.c:381
msgid ""
"Enter the new passphrase for this secret key.\n"
"\n"
msgstr ""
"÷×ÅÄÉÔÅ ÎÏ×ÕÀ ËÌÀÞÅ×ÕÀ ÆÒÁÚÕ ÄÌÑ ÜÔÏÇÏ ÓÅËÒÅÔÎÏÇÏ ËÌÀÞÁ.\n"
"\n"
#: g10/keyedit.c:393
msgid ""
"You don't want a passphrase - this is probably a *bad* idea!\n"
"\n"
msgstr ""
"÷Ù ÎÅ ÈÏÔÉÔÅ ËÌÀÞÅ×ÕÀ ÆÒÁÚÕ - ÜÔÏ ÓËÏÒÅÅ ×ÓÅÇÏ *ÐÌÏÈÁÑ* ÉÄÅÑ!\n"
"\n"
#: g10/keyedit.c:396
msgid "Do you really want to do this? "
msgstr "÷Ù ÄÅÊÓÔ×ÉÔÅÌØÎÏ ÜÔÏÇÏ ÈÏÔÉÔÅ? "
#: g10/keyedit.c:455
msgid "moving a key signature to the correct place\n"
msgstr ""
#: g10/keyedit.c:490
msgid "quit"
msgstr "×ÙÈÏÄ"
#: g10/keyedit.c:490
msgid "quit this menu"
msgstr "×ÙÊÔÉ ÉÚ ÍÅÎÀ"
#: g10/keyedit.c:491
msgid "q"
msgstr ""
#: g10/keyedit.c:492
msgid "save"
msgstr "ÚÁÐÉÓÁÔØ"
#: g10/keyedit.c:492
msgid "save and quit"
msgstr "ÚÁÐÉÓÁÔØ É ×ÙÊÔÉ"
#: g10/keyedit.c:493
msgid "help"
msgstr "ÐÏÍÏÝØ"
#: g10/keyedit.c:493
msgid "show this help"
msgstr "ÐÏËÁÚÁÔØ ÐÏÍÏÝØ"
#: g10/keyedit.c:495
msgid "fpr"
msgstr ""
#: g10/keyedit.c:495
#, fuzzy
msgid "show fingerprint"
msgstr "ÐÏËÁÚÁÔØ \"ÏÔÐÅÞÁÔÏË ÐÁÌØÃÁ\""
#: g10/keyedit.c:496
#, fuzzy
msgid "list"
msgstr "ÓÐÉÓÏË"
#: g10/keyedit.c:496
#, fuzzy
msgid "list key and user ids"
msgstr "ÓÐÉÓÏË ËÌÀÞÅÊ É ÉÄÅÎÔÉÆÉËÁÔÏÒÏ× ÐÏÌØÚÏ×ÁÔÅÌÅÊ"
#: g10/keyedit.c:497
msgid "l"
msgstr ""
#: g10/keyedit.c:498
msgid "uid"
msgstr ""
#: g10/keyedit.c:498
msgid "select user id N"
msgstr "×ÙÂÒÁÔØ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÏÌØÚÏ×ÁÔÅÌÑ N"
#: g10/keyedit.c:499
msgid "key"
msgstr "ËÌÀÞ"
#: g10/keyedit.c:499
msgid "select secondary key N"
msgstr "×ÙÂÒÁÔØ ÄÏÐÏÌÎÉÔÅÌØÎÙÊ ËÌÀÞ N"
#: g10/keyedit.c:500
msgid "check"
msgstr "ÐÒÏ×ÅÒËÁ"
#: g10/keyedit.c:500
#, fuzzy
msgid "list signatures"
msgstr "ÓÐÉÓÏË ËÌÀÞÅÊ É ÉÈ ÐÏÄÐÉÓÅÊ"
#: g10/keyedit.c:501
msgid "c"
msgstr ""
#: g10/keyedit.c:502
msgid "sign"
msgstr "ÐÏÄÐÉÓÁÔØ"
#: g10/keyedit.c:502
#, fuzzy
msgid "sign the key"
msgstr "ÐÏÄÐÉÓÁÔØ ËÌÀÞ"
#: g10/keyedit.c:503
msgid "s"
msgstr ""
#: g10/keyedit.c:504
msgid "debug"
msgstr "ÏÔÌÁÄËÁ"
#: g10/keyedit.c:505
msgid "adduid"
msgstr ""
#: g10/keyedit.c:505
msgid "add a user id"
msgstr "ÄÏÂÁ×ÉÔØ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÏÌØÚÏ×ÁÔÅÌÑ"
#: g10/keyedit.c:506
msgid "deluid"
msgstr ""
#: g10/keyedit.c:506
#, fuzzy
msgid "delete user id"
msgstr "ÕÄÁÌÉÔØ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÏÌØÚÏ×ÁÔÅÌÑ"
#: g10/keyedit.c:507
msgid "addkey"
msgstr ""
#: g10/keyedit.c:507
#, fuzzy
msgid "add a secondary key"
msgstr "ÄÏÂÁ×ÉÔØ ÄÏÐÏÌÎÉÔÅÌØÎÙÊ ËÌÀÞ"
#: g10/keyedit.c:508
msgid "delkey"
msgstr ""
#: g10/keyedit.c:508
msgid "delete a secondary key"
msgstr "ÕÄÁÌÉÔØ ÄÏÐÏÌÎÉÔÅÌØÎÙÊ ËÌÀÞ"
#: g10/keyedit.c:509
msgid "expire"
msgstr ""
#: g10/keyedit.c:509
#, fuzzy
msgid "change the expire date"
msgstr "ÉÚÍÅÎÉÔØ ËÌÀÞÅ×ÕÀ ÆÒÁÚÕ"
#: g10/keyedit.c:510
msgid "toggle"
msgstr ""
#: g10/keyedit.c:510
msgid "toggle between secret and public key listing"
msgstr "ÐÅÒÅËÌÀÞÉÔØ ÍÅÖÄÕ ÓÐÉÓËÏÍ ÓÅËÒÅÔÎÙÈ É ÏÔËÒÙÔÙÈ ËÌÀÞÅÊ"
#: g10/keyedit.c:512
msgid "t"
msgstr ""
#: g10/keyedit.c:513
msgid "pref"
msgstr ""
#: g10/keyedit.c:513
msgid "list preferences"
msgstr ""
#: g10/keyedit.c:514
msgid "passwd"
msgstr ""
#: g10/keyedit.c:514
#, fuzzy
msgid "change the passphrase"
msgstr "ÉÚÍÅÎÉÔØ ËÌÀÞÅ×ÕÀ ÆÒÁÚÕ"
#: g10/keyedit.c:515
msgid "trust"
msgstr ""
#: g10/keyedit.c:515
msgid "change the ownertrust"
msgstr "ÉÚÍÅÎÉÔØ ÐÁÒÁÍÅÔÒÙ ÄÏ×ÅÒÉÑ"
#: g10/keyedit.c:534
msgid "can't do that in batchmode\n"
msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÓÄÅÌÁÔØ ÜÔÏ × ÐÁËÅÔÎÏÍ ÒÅÖÉÍÅ.\n"
#. check that they match
#. FIXME: check that they both match
#: g10/keyedit.c:561
#, fuzzy
msgid "Secret key is available.\n"
msgstr "éÍÅÅÔÓÑ ÓÅËÒÅÔÎÙÊ ËÌÀÞ.\n"
#: g10/keyedit.c:590
#, fuzzy
msgid "Command> "
msgstr "ëÏÍÁÎÄÁ> "
#: g10/keyedit.c:617
#, fuzzy
msgid "Need the secret key to do this.\n"
msgstr "þÔÏÂÙ ÜÔÏ ÓÄÅÌÁÔØ, ÎÕÖÅÎ ÓÅËÒÅÔÎÙÊ ËÌÀÞ.\n"
#: g10/keyedit.c:639
msgid "Save changes? "
msgstr "óÏÈÒÁÎÉÔØ ÉÚÍÅÎÅÎÉÑ? "
#: g10/keyedit.c:642
msgid "Quit without saving? "
msgstr "÷ÙÊÔÉ ÂÅÚ ÓÏÈÒÁÎÅÎÉÑ? "
#: g10/keyedit.c:652
#, fuzzy, c-format
msgid "update failed: %s\n"
msgstr "ÏÂÎÏ×ÌÅÎÉÅ ÎÅ ÕÄÁÌÏÓØ: %s\n"
#: g10/keyedit.c:659
#, fuzzy, c-format
msgid "update secret failed: %s\n"
msgstr "ÏÂÎÏ×ÌÅÎÉÅ ÓÅËÒÅÔÁ ÎÅ ÕÄÁÌÏÓØ: %s\n"
#: g10/keyedit.c:666
msgid "Key not changed so no update needed.\n"
msgstr "ëÌÀÞ ÎÅ ÉÚÍÅÎÉÌÓÑ, ÏÂÎÏ×ÌÅÎÉÅ ÎÅ ÎÕÖÎÏ.\n"
#: g10/keyedit.c:669 g10/keyedit.c:727
#, fuzzy, c-format
msgid "update of trust db failed: %s\n"
msgstr "ÏÂÎÏ×ÌÅÎÉÅ ÂÁÚÙ ÄÁÎÎÙÈ ÄÏ×ÅÒÉÑ ÎÅ ÕÄÁÌÏÓØ: %s\n"
#: g10/keyedit.c:701
msgid "Really sign all user ids? "
msgstr "äÅÊÓÔ×ÉÔÅÌØÎÏ ÐÏÄÐÉÓÁÔØ ×ÓÅ ÉÄÅÎÔÉÆÉËÁÔÏÒÙ ÐÏÌØÚÏ×ÁÔÅÌÑ? "
#: g10/keyedit.c:702
msgid "Hint: Select the user ids to sign\n"
msgstr ""
"ðÏÄÓËÁÚËÁ: ×ÙÂÅÒÉÔÅ ÉÄÅÎÔÉÆÉËÁÔÏÒÙ ÐÏÌØÚÏ×ÁÔÅÌÑ ËÏÔÏÒÙÅ ÈÏÔÉÔÅ ÐÏÄÐÉÓÁÔØ\n"
#: g10/keyedit.c:738
msgid "You must select at least one user id.\n"
msgstr "÷Ù ÄÏÌÖÎÙ ×ÙÂÒÁÔØ ÈÏÔÑ ÂÙ ÏÄÉÎ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÏÌØÚÏ×ÁÔÅÌÑ.\n"
#: g10/keyedit.c:740
msgid "You can't delete the last user id!\n"
msgstr "÷Ù ÎÅ ÍÏÖÅÔÅ ÕÄÁÌÉÔØ ÐÏÓÌÅÄÎÉÊ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÏÌØÚÏ×ÁÔÅÌÑ!\n"
#: g10/keyedit.c:743
#, fuzzy
msgid "Really remove all selected user ids? "
msgstr "äÅÊÓÔ×ÉÔÅÌØÎÏ ÕÄÁÌÉÔØ ×ÓÅ ×ÙÂÒÁÎÎÙÅ ÉÄÅÎÔÉÆÉËÁÔÏÒÙ ÐÏÌØÚÏ×ÁÔÅÌÑ? "
#: g10/keyedit.c:744
#, fuzzy
msgid "Really remove this user id? "
msgstr "äÅÊÓÔ×ÉÔÅÌØÎÏ ÕÄÁÌÉÔØ ÜÔÏÔ ÉÄÅÎÔÉÆÉËÁÔÏÒ ÐÏÌØÚÏ×ÁÔÅÌÑ? "
#: g10/keyedit.c:767
msgid "You must select at least one key.\n"
msgstr "÷Ù ÄÏÌÖÎÙ ×ÙÂÒÁÔØ ÈÏÔÑ ÂÙ ÏÄÉÎ ËÌÀÞ.\n"
#: g10/keyedit.c:771
#, fuzzy
msgid "Do you really want to delete the selected keys? "
msgstr "÷Ù ÄÅÊÓÔ×ÉÔÅÌØÎÏ ÈÏÔÉÔÅ ÕÄÁÌÉÔØ ×ÙÂÒÁÎÎÙÅ ËÌÀÞÉ? "
#: g10/keyedit.c:772
#, fuzzy
msgid "Do you really want to delete this key? "
msgstr "÷Ù ÄÅÊÓÔ×ÉÔÅÌØÎÏ ÈÏÔÉÔÅ ÕÄÁÌÉÔØ ÜÔÏÔ ËÌÀÞ? "
#: g10/keyedit.c:819
msgid "Invalid command (try \"help\")\n"
msgstr "îÅÄÏÐÕÓÔÉÍÁÑ ËÏÍÁÎÄÁ (ÐÏÐÒÏÂÕÊÔÅ \"help\")\n"
#: g10/keyedit.c:1197
msgid "Please remove selections from the secret keys.\n"
msgstr ""
#: g10/keyedit.c:1203
#, fuzzy
msgid "Please select at most one secondary key.\n"
msgstr "÷Ù ÄÏÌÖÎÙ ×ÙÂÒÁÔØ ÈÏÔÑ ÂÙ ÏÄÉÎ ËÌÀÞ.\n"
#: g10/keyedit.c:1207
msgid "Changing exiration time for a secondary key.\n"
msgstr ""
#: g10/keyedit.c:1209
msgid "Changing exiration time for the primary key.\n"
msgstr ""
#: g10/keyedit.c:1250
msgid "You can't change the expiration date of a v3 key\n"
msgstr ""
#: g10/keyedit.c:1266
msgid "No corresponding signature in secret ring\n"
msgstr ""
#: g10/keyedit.c:1326
#, c-format
msgid "No user id with index %d\n"
msgstr "îÅÔ ÉÄÅÎÔÉÆÉËÁÔÏÒÁ ÐÏÌØÚÏ×ÁÔÅÌÑ Ó ÉÎÄÅËÓÏÍ %d\n"
#: g10/keyedit.c:1371
#, c-format
msgid "No secondary key with index %d\n"
msgstr "îÅÔ ÄÏÐÏÌÎÉÔÅÌØÎÏÇÏ ËÌÀÞÁ Ó ÉÎÄÅËÓÏÍ %d\n"
#: g10/mainproc.c:198
#, fuzzy
msgid "public key encrypted data: Good DEK\n"
msgstr "ÒÁÓÛÉÆÒÏ×ËÁ ÏÔËÒÙÔÙÍ ËÌÀÞÏÍ ÎÅ ÕÄÁÌÁÓØ %s\n"
#: g10/mainproc.c:201
#, c-format
msgid "public key decryption failed: %s\n"
msgstr "ÒÁÓÛÉÆÒÏ×ËÁ ÏÔËÒÙÔÙÍ ËÌÀÞÏÍ ÎÅ ÕÄÁÌÁÓØ %s\n"
#: g10/mainproc.c:228
#, fuzzy
msgid "decryption okay\n"
msgstr "ÒÁÓÛÉÆÒÏ×ËÁ ÎÅ ÕÄÁÌÁÓØ: %s\n"
#: g10/mainproc.c:231
#, c-format
msgid "decryption failed: %s\n"
msgstr "ÒÁÓÛÉÆÒÏ×ËÁ ÎÅ ÕÄÁÌÁÓØ: %s\n"
#: g10/mainproc.c:248
#, fuzzy
msgid "NOTE: sender requested \"for-your-eyes-only\"\n"
msgstr "ÚÁÍÅÞÁÎÉÅ: ÏÔÐÒÁ×ÉÔÅÌØ ÚÁÐÒÏÓÉÌ \"ÔÏÌØËÏ-ÄÌÑ-÷ÁÛÉÈ-ÇÌÁÚ\"\n"
#: g10/mainproc.c:250
#, c-format
msgid "original file name='%.*s'\n"
msgstr ""
#: g10/mainproc.c:833
msgid "signature verification suppressed\n"
msgstr ""
#: g10/mainproc.c:839
#, c-format
msgid "Signature made %.*s using %s key ID %08lX\n"
msgstr "ðÏÄÐÉÓØ ÓÄÅÌÁÎÁ %.*s, ÉÓÐÏÌØÚÕÑ %s ËÌÀÞ %08lX\n"
#: g10/mainproc.c:847
msgid "BAD signature from \""
msgstr "ðìïèáñ ÐÏÄÐÉÓØ ÏÔ \""
#: g10/mainproc.c:848
msgid "Good signature from \""
msgstr "èÏÒÏÛÁÑ ÐÏÄÐÉÓØ ÏÔ \""
#: g10/mainproc.c:861
#, c-format
msgid "Can't check signature: %s\n"
msgstr "îÅ×ÏÚÍÏÖÎÏ ÐÒÏ×ÅÒÉÔØ ÐÏÄÐÉÓØ: %s\n"
#: g10/mainproc.c:934
msgid "old style (PGP 2.x) signature\n"
msgstr ""
#: g10/mainproc.c:939
msgid "invalid root packet detected in proc_tree()\n"
msgstr ""
#: g10/misc.c:88
#, fuzzy, c-format
msgid "can't disable core dumps: %s\n"
msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ '%s': %s\n"
#: g10/misc.c:90
msgid "WARNING: Program may create a core file!\n"
msgstr ""
#: g10/misc.c:198
msgid "Experimental algorithms should not be used!\n"
msgstr ""
#: g10/misc.c:212
msgid ""
"RSA keys are deprecated; please consider creating a new key and use this key "
"in the future\n"
msgstr ""
"ðÏÌØÚÏ×ÁÎÉÅ RSA ËÌÀÞÁÍÉ ÎÅ ÒÅËÏÍÅÎÄÕÅÔÓÑ, ÐÏÖÁÌÕÊÓÔÁ, ÐÏÄÕÍÁÊÔÅ Ï ÓÏÚÄÁÎÉÉ\n"
"ÎÏ×ÏÇÏ ËÌÀÞÁ ÄÌÑ ÉÓÐÏÌØÚÏ×ÁÎÉÑ × ÂÕÄÕÝÅÍ\n"
#: g10/misc.c:233
msgid "This cipher algorithm is depreciated; please use a more standard one!\n"
msgstr ""
#: g10/parse-packet.c:109
#, fuzzy, c-format
msgid "can't handle public key algorithm %d\n"
msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÚÁÂÌÏËÉÒÏ×ÁÔØ Ó×ÑÚËÕ ÏÔËÒÙÔÙÈ ËÌÀÞÅÊ: %s\n"
+#: g10/parse-packet.c:801
+#, c-format
+msgid "subpacket of type %d has critical bit set\n"
+msgstr ""
+
#: g10/passphrase.c:141
msgid ""
"\n"
"You need a passphrase to unlock the secret key for\n"
"user: \""
msgstr ""
"\n"
"÷ÁÍ ÎÕÖÎÁ ËÌÀÞÅ×ÁÑ ÆÒÁÚÁ, ÞÔÏÂÙ ÏÔÏÍËÎÕÔØ ËÌÀÞ\n"
"ÐÏÌØÚÏ×ÁÔÅÌÑ: \""
#: g10/passphrase.c:150
#, c-format
msgid "(%u-bit %s key, ID %08lX, created %s)\n"
msgstr "(%u-ÂÉÔ %s ËÌÀÞ, ID %08lX, ÓÏÚÄÁÎ %s)\n"
#: g10/passphrase.c:174
#, fuzzy
msgid "Enter passphrase: "
msgstr "÷×ÅÄÉÔÅ ËÌÀÞÅ×ÕÀ ÆÒÁÚÕ: %s\n"
#: g10/passphrase.c:178
#, fuzzy
msgid "Repeat passphrase: "
msgstr "ðÏ×ÔÏÒÉÔÅ ËÌÀÞÅ×ÕÀ ÆÒÁÚÕ: %s\n"
-#: g10/plaintext.c:102
+#: g10/plaintext.c:103
msgid "data not saved; use option \"--output\" to save it\n"
msgstr "ÄÁÎÎÙÅ ÎÅ ÂÙÌÉ ÓÏÈÒÁÎÅÎÙ; ×ÏÓÐÏÌØÚÕÊÔÅÓØ --\"output\" ÄÌÑ ÓÏÈÒÁÎÅÎÉÑ\n"
-#: g10/plaintext.c:215
+#: g10/plaintext.c:216
msgid "Please enter name of data file: "
msgstr "ðÏÖÁÌÕÊÓÔÁ, ××ÅÄÉÔÅ ÉÍÑ ÆÁÊÌÁ ÄÁÎÎÙÈ: "
-#: g10/plaintext.c:236
+#: g10/plaintext.c:237
msgid "reading stdin ...\n"
msgstr ""
-#: g10/plaintext.c:299
+#: g10/plaintext.c:300
#, c-format
msgid "can't open signed data '%s'\n"
msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÐÏÄÐÉÓÁÎÎÙÅ ÄÁÎÎÙÅ '%s' .\n"
#: g10/pubkey-enc.c:78
#, c-format
msgid "anonymous receiver; trying secret key %08lX ...\n"
msgstr "ÁÎÏÎÉÍÎÙÊ ÐÏÌÕÞÁÔÅÌØ, ÐÒÏÂÕÅÍ ÓÅËÒÅÔÎÙÊ ËÌÀÞ %08lX ...\n"
#: g10/pubkey-enc.c:84
msgid "okay, we are the anonymous receiver.\n"
msgstr "ïË, ÍÙ -- ÁÎÏÎÉÍÎÙÊ ÐÏÌÕÞÁÔÅÌØ.\n"
#: g10/pubkey-enc.c:136
#, fuzzy
msgid "old encoding of the DEK is not supported\n"
msgstr "ÁÌÇÏÒÉÔÍ ÚÁÝÉÔÙ %d ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ\n"
#: g10/pubkey-enc.c:183
#, fuzzy, c-format
msgid "NOTE: cipher algorithm %d not found in preferences\n"
msgstr "ÚÁÍÅÞÁÎÉÅ: ÛÉÆÒÏ×ÁÌØÎÙÊ ÁÌÇÏÒÉÔÍ %d ÎÅ ÎÁÊÄÅÎ × ÐÒÅÄÐÏÞÔÅÎÉÑÈ\n"
#: g10/seckey-cert.c:56
#, fuzzy, c-format
msgid "protection algorithm %d is not supported\n"
msgstr "ÁÌÇÏÒÉÔÍ ÚÁÝÉÔÙ %d ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ\n"
#: g10/seckey-cert.c:169
msgid "Invalid passphrase; please try again ...\n"
msgstr "îÅÐÒÁ×ÉÌØÎÁÑ ËÌÀÞÅ×ÁÑ ÆÒÁÚÁ, ÐÏÐÒÏÂÕÊÔÅ ÓÎÏ×Á ...\n"
#: g10/seckey-cert.c:216
#, fuzzy
msgid "WARNING: Weak key detected - please change passphrase again.\n"
msgstr "ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÏÂÎÁÒÕÖÅÎ ÓÌÁÂÙÊ ËÌÀÞ - ÓÍÅÎÉÔÅ ËÌÀÞÅ×ÕÀ ÆÒÁÚÕ.\n"
#: g10/sig-check.c:155
msgid ""
"this is a PGP generated ElGamal key which is NOT secure for signatures!\n"
msgstr "ÜÔÏÔ ElGamal ËÌÀÞ, ÓÏÚÄÁÎÎÙÊ PGP, ÎÅ ÎÁÄÅÖÅÎ ÄÌÑ ÓÏÚÄÁÎÉÑ ÐÏÄÐÉÓÅÊ!\n"
#: g10/sig-check.c:165
msgid "public key created in future (time warp or clock problem)\n"
msgstr ""
"ÏÔËÒÙÔÙÊ ËÌÀÞ ÓÇÅÎÅÒÉÒÏ×ÁÎ × ÂÕÄÕÝÅÍ (ÉÓËÒÉ×ÌÅÎÉÅ ×ÒÅÍÅÎÉ ÉÌÉ ÎÅÐÒÁ×ÉÌØÎÏ "
"ÕÓÔÁÎÏ×ÌÅÎÙ ÞÁÓÙ)\n"
#: g10/sig-check.c:170
#, fuzzy, c-format
msgid "NOTE: signature key expired %s\n"
msgstr "ÐÒÅÄÕÐÒÅÖÄÅÎÉÅ: ËÌÀÞ ÐÏÄÐÉÓÉ ÕÓÔÁÒÅÌ %s\n"
+#: g10/sig-check.c:226
+msgid "assuming bad signature due to an unknown critical bit\n"
+msgstr ""
+
#: g10/sign.c:69
#, fuzzy, c-format
msgid "%s signature from: %s\n"
msgstr "ðìïèáñ ÐÏÄÐÉÓØ ÏÔ \""
-#: g10/sign.c:200 g10/sign.c:564
+#: g10/sign.c:200 g10/sign.c:587
#, fuzzy, c-format
msgid "can't create %s: %s\n"
msgstr "%s: ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ: %s\n"
#: g10/sign.c:296
#, fuzzy
msgid "signing:"
msgstr "ÐÏÄÐÉÓÁÔØ"
#: g10/sign.c:336
#, fuzzy, c-format
msgid "WARNING: '%s' is an empty file\n"
msgstr "%s: ÐÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÐÕÓÔÏÊ ÆÁÊÌ.\n"
#: g10/tdbio.c:116 g10/tdbio.c:1413
#, fuzzy, c-format
msgid "trustdb rec %lu: lseek failed: %s\n"
msgstr "ÏÂÎÏ×ÌÅÎÉÅ ÓÅËÒÅÔÁ ÎÅ ÕÄÁÌÏÓØ: %s\n"
#: g10/tdbio.c:122 g10/tdbio.c:1420
#, c-format
msgid "trustdb rec %lu: write failed (n=%d): %s\n"
msgstr ""
#: g10/tdbio.c:232
msgid "trustdb transaction to large\n"
msgstr ""
#: g10/tdbio.c:402
#, fuzzy, c-format
msgid "%s: can't access: %s\n"
msgstr "%s: ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ: %s\n"
#: g10/ringedit.c:273 g10/tdbio.c:422
#, fuzzy, c-format
msgid "%s: can't create directory: %s\n"
msgstr "%s: ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ: %s\n"
#: g10/ringedit.c:279 g10/tdbio.c:425
#, fuzzy, c-format
msgid "%s: directory created\n"
msgstr "%s: ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ: %s\n"
#: g10/tdbio.c:429
#, c-format
msgid "%s: directory does not exist!\n"
msgstr ""
#: g10/openfile.c:101 g10/openfile.c:165 g10/ringedit.c:1256 g10/tdbio.c:435
#, fuzzy, c-format
msgid "%s: can't create: %s\n"
msgstr "%s: ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ: %s\n"
#: g10/tdbio.c:459
#, c-format
msgid "%s: failed to create version record: %s"
msgstr ""
#: g10/tdbio.c:463
#, c-format
msgid "%s: invalid trust-db created\n"
msgstr ""
#: g10/tdbio.c:465
#, fuzzy, c-format
msgid "%s: trust-db created\n"
msgstr "%s: ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ: %s\n"
#: g10/tdbio.c:506
#, c-format
msgid "%s: invalid trust-db\n"
msgstr ""
#: g10/tdbio.c:540
#, fuzzy, c-format
msgid "%s: failed to create hashtable: %s\n"
msgstr "%s: ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ: %s\n"
#: g10/tdbio.c:548
#, fuzzy, c-format
msgid "%s: error updating version record: %s\n"
msgstr "Fehler beim Erzeugen der \"Passphrase\": %s\n"
#: g10/tdbio.c:564 g10/tdbio.c:603 g10/tdbio.c:628 g10/tdbio.c:1346
#: g10/tdbio.c:1373
#, fuzzy, c-format
msgid "%s: error reading version record: %s\n"
msgstr "Fehler beim Erzeugen der \"Passphrase\": %s\n"
#: g10/tdbio.c:577
#, fuzzy, c-format
msgid "%s: error writing version record: %s\n"
msgstr "Fehler beim Erzeugen der \"Passphrase\": %s\n"
#: g10/tdbio.c:1053
#, fuzzy, c-format
msgid "trustdb: lseek failed: %s\n"
msgstr "ÏÂÎÏ×ÌÅÎÉÅ ÓÅËÒÅÔÁ ÎÅ ÕÄÁÌÏÓØ: %s\n"
#: g10/tdbio.c:1061
#, fuzzy, c-format
msgid "trustdb: read failed (n=%d): %s\n"
msgstr "ÏÂÎÏ×ÌÅÎÉÅ ÂÁÚÙ ÄÁÎÎÙÈ ÄÏ×ÅÒÉÑ ÎÅ ÕÄÁÌÏÓØ: %s\n"
#: g10/tdbio.c:1082
#, fuzzy, c-format
msgid "%s: not a trustdb file\n"
msgstr "ÏÂÎÏ×ÌÅÎÉÅ ÂÁÚÙ ÄÁÎÎÙÈ ÄÏ×ÅÒÉÑ ÎÅ ÕÄÁÌÏÓØ: %s\n"
#: g10/tdbio.c:1098
#, c-format
msgid "%s: version record with recnum %lu\n"
msgstr ""
#: g10/tdbio.c:1103
#, fuzzy, c-format
msgid "%s: invalid file version %d\n"
msgstr "ÎÅÄÏÐÕÓÔÉÍÏÅ ÎÁÞÁÌÏ ÔÅËÓÔÏ×ÏÊ ÐÏÄÐÉÓÉ\n"
#: g10/tdbio.c:1379
#, fuzzy, c-format
msgid "%s: error reading free record: %s\n"
msgstr "Fehler beim Erzeugen der \"Passphrase\": %s\n"
#: g10/tdbio.c:1387
#, fuzzy, c-format
msgid "%s: error writing dir record: %s\n"
msgstr "Fehler beim Erzeugen der \"Passphrase\": %s\n"
#: g10/tdbio.c:1397
#, c-format
msgid "%s: failed to zero a record: %s\n"
msgstr ""
#: g10/tdbio.c:1427
#, c-format
msgid "%s: failed to append a record: %s\n"
msgstr ""
-#: g10/trustdb.c:134
+#: g10/trustdb.c:142
msgid "The trust DB is corrupted; please run \"gpgm --fix-trust-db\".\n"
msgstr "âÁÚÁ ÄÁÎÎÙÈ ÄÏ×ÅÒÉÑ ÒÁÚÒÕÛÅÎÁ: ÚÁÐÕÓÔÉÔÅ \"gpgm --fix-trust-db\".\n"
-#: g10/trustdb.c:147
+#: g10/trustdb.c:155
#, c-format
msgid "trust record %lu, req type %d: read failed: %s\n"
msgstr ""
-#: g10/trustdb.c:162
+#: g10/trustdb.c:170
#, c-format
msgid "trust record %lu, type %d: write failed: %s\n"
msgstr ""
-#: g10/trustdb.c:176
+#: g10/trustdb.c:184
#, fuzzy, c-format
msgid "trust record %lu: delete failed: %s\n"
msgstr "ÏÂÎÏ×ÌÅÎÉÅ ÓÅËÒÅÔÁ ÎÅ ÕÄÁÌÏÓØ: %s\n"
-#: g10/trustdb.c:190
+#: g10/trustdb.c:198
#, fuzzy, c-format
msgid "trust db: sync failed: %s\n"
msgstr "ÏÂÎÏ×ÌÅÎÉÅ ÂÁÚÙ ÄÁÎÎÙÈ ÄÏ×ÅÒÉÑ ÎÅ ÕÄÁÌÏÓØ: %s\n"
-#: g10/trustdb.c:319
+#: g10/trustdb.c:327
#, fuzzy, c-format
msgid "error reading dir record for LID %lu: %s\n"
msgstr "Fehler beim Erzeugen der \"Passphrase\": %s\n"
-#: g10/trustdb.c:326
+#: g10/trustdb.c:334
#, c-format
msgid "lid %lu: expected dir record, got type %d\n"
msgstr ""
-#: g10/trustdb.c:331
+#: g10/trustdb.c:339
#, c-format
msgid "no primary key for LID %lu\n"
msgstr ""
-#: g10/trustdb.c:336
+#: g10/trustdb.c:344
#, fuzzy, c-format
msgid "error reading primary key for LID %lu: %s\n"
msgstr "Fehler beim Erzeugen der \"Passphrase\": %s\n"
-#: g10/trustdb.c:412
+#: g10/trustdb.c:420
#, c-format
msgid "chained sigrec %lu has a wrong owner\n"
msgstr ""
-#: g10/trustdb.c:455
+#: g10/trustdb.c:463
#, fuzzy, c-format
msgid "'%s' is not a valid long keyID\n"
msgstr "îÅÄÏÐÕÓÔÉÍÙÊ ÓÉÍ×ÏÌ × ËÏÍÍÅÎÔÁÒÉÉ.\n"
-#: g10/trustdb.c:490
+#: g10/trustdb.c:498
#, fuzzy, c-format
msgid "key %08lX: no public key for trusted key - skipped\n"
msgstr "ÓÅËÒÅÔÎÙÊ ËÌÀÞ %08lX: ÎÅ ÉÍÅÅÔ ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÅÇÏ ÏÔËÒÙÔÏÇÏ ËÌÀÞÁ.\n"
-#: g10/trustdb.c:499 g10/trustdb.c:557
+#: g10/trustdb.c:507 g10/trustdb.c:565
#, fuzzy, c-format
msgid "key %08lX: can't put it into the trustdb\n"
msgstr "ËÌÀÞ %08lX.%lu: ÎÅ×ÏÚÍÏÖÎÏ ÐÏÌÏÖÉÔØ × ÂÁÚÕ ÄÁÎÎÙÈ ÄÏ×ÅÒÉÑ\n"
-#: g10/trustdb.c:504 g10/trustdb.c:563
+#: g10/trustdb.c:512 g10/trustdb.c:571
#, fuzzy, c-format
msgid "key %08lX: query record failed\n"
msgstr "ËÌÀÞ %08lX: ÚÁÐÒÏÓ ÚÁÐÉÓÉ ÎÅ ÕÄÁÌÓÑ\n"
-#: g10/trustdb.c:509 g10/trustdb.c:572
+#: g10/trustdb.c:517 g10/trustdb.c:580
#, fuzzy, c-format
msgid "key %08lX: already in trusted key table\n"
msgstr "ËÌÀÞ %08lX: ÕÖÅ ÎÁ Ó×ÑÚËÅ ÓÅËÒÅÔÎÙÈ ËÌÀÞÅÊ\n"
-#: g10/trustdb.c:512 g10/trustdb.c:575
+#: g10/trustdb.c:520 g10/trustdb.c:583
#, fuzzy, c-format
msgid "key %08lX: accepted as trusted key.\n"
msgstr "ËÌÀÞ %08lX: ÕÖÅ ÎÁ Ó×ÑÚËÅ ÓÅËÒÅÔÎÙÈ ËÌÀÞÅÊ\n"
-#: g10/trustdb.c:528
+#: g10/trustdb.c:536
#, fuzzy, c-format
msgid "NOTE: secret key %08lX is NOT protected.\n"
msgstr "üÔÏÔ ËÌÀÞ ÎÅ ÚÁÝÉÝÅÎ.\n"
-#: g10/trustdb.c:540
+#: g10/trustdb.c:548
#, fuzzy, c-format
msgid "key %08lX: secret key without public key - skipped\n"
msgstr "ÓÅËÒÅÔÎÙÊ ËÌÀÞ %08lX: ÎÅ ÉÍÅÅÔ ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÅÇÏ ÏÔËÒÙÔÏÇÏ ËÌÀÞÁ.\n"
-#: g10/trustdb.c:547
+#: g10/trustdb.c:555
#, c-format
msgid "key %08lX: secret and public key don't match\n"
msgstr "ËÌÀÞ %08lX: ÓÅËÒÅÔÎÙÊ É ÏÔËÒÙÔÏÇÏ ËÌÀÞÉ ÎÅ ÓÏ×ÐÁÄÁÀÔ.\n"
-#: g10/trustdb.c:583
+#: g10/trustdb.c:591
#, fuzzy, c-format
msgid "enumerate secret keys failed: %s\n"
msgstr "ÏÂÎÏ×ÌÅÎÉÅ ÓÅËÒÅÔÁ ÎÅ ÕÄÁÌÏÓØ: %s\n"
-#: g10/trustdb.c:766
+#: g10/trustdb.c:774
#, fuzzy, c-format
msgid "lid %lu: read dir record failed: %s\n"
msgstr "ËÌÀÞ %08lX.%lu: ×ÓÔÁ×ËÁ ÄÏ×ÅÒÉÔÅÌØÎÏÊ ÚÁÐÉÓÉ ÎÅ ÕÄÁÌÁÓØ: %s\n"
-#: g10/trustdb.c:775
+#: g10/trustdb.c:783
#, fuzzy, c-format
msgid "lid %lu: read key record failed: %s\n"
msgstr "ËÌÀÞ %08lX.%lu: ×ÓÔÁ×ËÁ ÄÏ×ÅÒÉÔÅÌØÎÏÊ ÚÁÐÉÓÉ ÎÅ ÕÄÁÌÁÓØ: %s\n"
-#: g10/trustdb.c:785
+#: g10/trustdb.c:793
#, fuzzy, c-format
msgid "lid %lu: read uid record failed: %s\n"
msgstr "ËÌÀÞ %08lX.%lu: ×ÓÔÁ×ËÁ ÄÏ×ÅÒÉÔÅÌØÎÏÊ ÚÁÐÉÓÉ ÎÅ ÕÄÁÌÁÓØ: %s\n"
-#: g10/trustdb.c:794
+#: g10/trustdb.c:802
#, fuzzy, c-format
msgid "lid %lu: read pref record failed: %s\n"
msgstr "ËÌÀÞ %08lX.%lu: ×ÓÔÁ×ËÁ ÄÏ×ÅÒÉÔÅÌØÎÏÊ ÚÁÐÉÓÉ ÎÅ ÕÄÁÌÁÓØ: %s\n"
-#: g10/trustdb.c:804
+#: g10/trustdb.c:812
#, fuzzy, c-format
msgid "lid %lu: read sig record failed: %s\n"
msgstr "ËÌÀÞ %08lX.%lu: ×ÓÔÁ×ËÁ ÄÏ×ÅÒÉÔÅÌØÎÏÊ ÚÁÐÉÓÉ ÎÅ ÕÄÁÌÁÓØ: %s\n"
-#: g10/trustdb.c:999
+#: g10/trustdb.c:1013
msgid "Ooops, no keys\n"
msgstr ""
-#: g10/trustdb.c:1003
+#: g10/trustdb.c:1017
#, fuzzy
msgid "Ooops, no user ids\n"
msgstr "ÓÐÉÓÏË ËÌÀÞÅÊ É ÉÄÅÎÔÉÆÉËÁÔÏÒÏ× ÐÏÌØÚÏ×ÁÔÅÌÅÊ"
-#: g10/trustdb.c:1074 g10/trustdb.c:1092
+#: g10/trustdb.c:1088 g10/trustdb.c:1106
#, c-format
msgid "user '%s' read problem: %s\n"
msgstr ""
-#: g10/trustdb.c:1077 g10/trustdb.c:1095
+#: g10/trustdb.c:1091 g10/trustdb.c:1109
#, c-format
msgid "user '%s' list problem: %s\n"
msgstr ""
-#: g10/trustdb.c:1085 g10/trustdb.c:1300
+#: g10/trustdb.c:1099 g10/trustdb.c:1346
#, fuzzy, c-format
msgid "user '%s' not found: %s\n"
msgstr "%s: ÐÏÌØÚÏ×ÁÔÅÌØ ÎÅ ÎÁÊÄÅÎ\n"
-#: g10/trustdb.c:1087 g10/trustdb.c:1302
+#: g10/trustdb.c:1101 g10/trustdb.c:1348
#, c-format
msgid "problem finding '%s' in trustdb: %s\n"
msgstr ""
-#: g10/trustdb.c:1090
+#: g10/trustdb.c:1104
#, c-format
msgid "user '%s' not in trustdb\n"
msgstr ""
-#: g10/trustdb.c:1125
+#: g10/trustdb.c:1139
#, c-format
msgid ""
"# List of assigned trustvalues, created %s\n"
"# (Use \"gpgm --import-ownertrust\" to restore them)\n"
msgstr ""
-#: g10/trustdb.c:1131
+#: g10/trustdb.c:1145
msgid "directory record w/o primary key\n"
msgstr ""
-#: g10/trustdb.c:1138
+#: g10/trustdb.c:1152
#, fuzzy, c-format
msgid "error reading key record: %s\n"
msgstr "Fehler beim Erzeugen der \"Passphrase\": %s\n"
-#: g10/trustdb.c:1178
+#: g10/trustdb.c:1192
msgid "line too long\n"
msgstr ""
-#: g10/trustdb.c:1186
+#: g10/trustdb.c:1200
msgid "error: missing colon\n"
msgstr ""
-#: g10/trustdb.c:1191
+#: g10/trustdb.c:1205
#, fuzzy
msgid "error: invalid fingerprint\n"
msgstr "ÏÛÉÂËÁ × ÚÁ×ÅÒÛÁÀÝÅÊ ÓÔÒÏËÅ\n"
-#: g10/trustdb.c:1195
+#: g10/trustdb.c:1209
#, fuzzy
msgid "error: no ownertrust value\n"
msgstr "ÜËÓÐÏÒÔÉÒÏ×ÁÔØ ÐÁÒÁÍÅÔÒÙ ÄÏ×ÅÒÉÑ\n"
-#: g10/trustdb.c:1209
+#: g10/trustdb.c:1223
#, c-format
msgid "LID %lu: changing trust from %u to %u\n"
msgstr ""
-#: g10/trustdb.c:1212
+#: g10/trustdb.c:1226
#, c-format
msgid "LID %lu: setting trust to %u\n"
msgstr ""
-#: g10/trustdb.c:1220
+#: g10/trustdb.c:1234
msgid "key not in trustdb, searching ring.\n"
msgstr ""
-#: g10/trustdb.c:1223
+#: g10/trustdb.c:1237
#, fuzzy, c-format
msgid "key not in ring: %s\n"
msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÚÁÐÉÓÁÔØ Ó×ÑÚËÕ ËÌÀÞÅÊ: %s\n"
-#: g10/trustdb.c:1227
+#: g10/trustdb.c:1241
msgid "Oops: key is now in trustdb???\n"
msgstr ""
#. update the ownertrust
-#: g10/trustdb.c:1232
+#: g10/trustdb.c:1246
#, fuzzy, c-format
msgid "insert trust record failed: %s\n"
msgstr "ËÌÀÞ %08lX.%lu: ×ÓÔÁ×ËÁ ÄÏ×ÅÒÉÔÅÌØÎÏÊ ÚÁÐÉÓÉ ÎÅ ÕÄÁÌÁÓØ: %s\n"
#. error
-#: g10/trustdb.c:1238
+#: g10/trustdb.c:1252
#, fuzzy, c-format
msgid "error finding dir record: %s\n"
msgstr "Fehler beim Erzeugen der \"Passphrase\": %s\n"
-#: g10/trustdb.c:1305
+#: g10/trustdb.c:1351
#, c-format
msgid "user '%s' not in trustdb - inserting\n"
msgstr ""
-#: g10/trustdb.c:1308
+#: g10/trustdb.c:1354
#, fuzzy, c-format
msgid "failed to put '%s' into trustdb: %s\n"
msgstr "ïÛÉÂËÁ ÉÎÉÃÉÁÌÉÚÁÃÉÉ ÂÁÚÙ ÄÁÎÎÙÈ ÄÏ×ÅÒÉÑ: %s\n"
-#: g10/trustdb.c:1355
+#: g10/trustdb.c:1404
#, c-format
msgid "%s: keyblock read problem: %s\n"
msgstr ""
-#: g10/trustdb.c:1369
+#: g10/trustdb.c:1418
#, fuzzy, c-format
msgid "%s: update failed: %s\n"
msgstr "ÏÂÎÏ×ÌÅÎÉÅ ÎÅ ÕÄÁÌÏÓØ: %s\n"
-#: g10/trustdb.c:1372
+#: g10/trustdb.c:1421
#, c-format
msgid "%s: updated\n"
msgstr ""
-#: g10/trustdb.c:1374
+#: g10/trustdb.c:1423
#, c-format
msgid "%s: okay\n"
msgstr ""
-#: g10/trustdb.c:1389
+#: g10/trustdb.c:1438
#, c-format
msgid "lid %lu: dir record w/o key - skipped\n"
msgstr ""
-#: g10/trustdb.c:1402
+#: g10/trustdb.c:1451
#, fuzzy, c-format
msgid "lid %lu: keyblock not found: %s\n"
msgstr "ËÌÀÞ %08lX: ÏÔËÒÙÔÙÊ ËÌÀÞ ÎÅ ÎÁÊÄÅÎ: %s\n"
-#: g10/trustdb.c:1411 g10/trustdb.c:1480
+#: g10/trustdb.c:1460 g10/trustdb.c:1529
#, fuzzy, c-format
msgid "lid %lu: update failed: %s\n"
msgstr "ÏÂÎÏ×ÌÅÎÉÅ ÎÅ ÕÄÁÌÏÓØ: %s\n"
-#: g10/trustdb.c:1417 g10/trustdb.c:1486
+#: g10/trustdb.c:1466 g10/trustdb.c:1535
#, c-format
msgid "lid %lu: updated\n"
msgstr ""
-#: g10/trustdb.c:1421 g10/trustdb.c:1490
+#: g10/trustdb.c:1470 g10/trustdb.c:1539
#, c-format
msgid "lid %lu: okay\n"
msgstr ""
-#: g10/trustdb.c:1428 g10/trustdb.c:1496
+#: g10/trustdb.c:1477 g10/trustdb.c:1545
#, c-format
msgid "%lu keys processed\n"
msgstr ""
-#: g10/trustdb.c:1430
+#: g10/trustdb.c:1479
#, fuzzy, c-format
msgid "\t%lu keys skipped\n"
msgstr "%s: ÐÒÏÐÕÝÅÎ: %s\n"
-#: g10/trustdb.c:1432 g10/trustdb.c:1498
+#: g10/trustdb.c:1481 g10/trustdb.c:1547
#, fuzzy, c-format
msgid "\t%lu keys with errors\n"
msgstr "ïÛÉÂËÁ ÚÁÐÉÓÉ ÆÁÊÌÁ"
-#: g10/trustdb.c:1434 g10/trustdb.c:1500
+#: g10/trustdb.c:1483 g10/trustdb.c:1549
#, c-format
msgid "\t%lu keys updated\n"
msgstr ""
-#: g10/trustdb.c:1464
+#: g10/trustdb.c:1513
#, fuzzy, c-format
msgid "lid ?: insert failed: %s\n"
msgstr "ÏÂÎÏ×ÌÅÎÉÅ ÓÅËÒÅÔÁ ÎÅ ÕÄÁÌÏÓØ: %s\n"
-#: g10/trustdb.c:1469
+#: g10/trustdb.c:1518
#, fuzzy, c-format
msgid "lid %lu: insert failed: %s\n"
msgstr "ÏÂÎÏ×ÌÅÎÉÅ ÓÅËÒÅÔÁ ÎÅ ÕÄÁÌÏÓØ: %s\n"
-#: g10/trustdb.c:1475
+#: g10/trustdb.c:1524
#, c-format
msgid "lid %lu: inserted\n"
msgstr ""
-#: g10/trustdb.c:1502
+#: g10/trustdb.c:1551
#, c-format
msgid "\t%lu keys inserted\n"
msgstr ""
-#: g10/trustdb.c:1505
+#: g10/trustdb.c:1554
#, fuzzy, c-format
msgid "enumerate keyblocks failed: %s\n"
msgstr "ÏÂÎÏ×ÌÅÎÉÅ ÓÅËÒÅÔÁ ÎÅ ÕÄÁÌÏÓØ: %s\n"
-#: g10/trustdb.c:1550
+#: g10/trustdb.c:1599
#, fuzzy, c-format
msgid "check_trust: search dir record failed: %s\n"
msgstr "ËÌÀÞ %08lX.%lu: ×ÓÔÁ×ËÁ ÄÏ×ÅÒÉÔÅÌØÎÏÊ ÚÁÐÉÓÉ ÎÅ ÕÄÁÌÁÓØ: %s\n"
-#: g10/trustdb.c:1557
+#: g10/trustdb.c:1606
#, fuzzy, c-format
msgid "key %08lX: insert trust record failed: %s\n"
msgstr "ËÌÀÞ %08lX.%lu: ×ÓÔÁ×ËÁ ÄÏ×ÅÒÉÔÅÌØÎÏÊ ÚÁÐÉÓÉ ÎÅ ÕÄÁÌÁÓØ: %s\n"
-#: g10/trustdb.c:1561
+#: g10/trustdb.c:1610
#, c-format
msgid "key %08lX.%lu: inserted into trustdb\n"
msgstr "ËÌÀÞ %08lX.%lu: ×ÓÔÁ×ÌÅÎ × ÂÁÚÕ ÄÁÎÎÙÈ ÄÏ×ÅÒÉÑ\n"
-#: g10/trustdb.c:1569
+#: g10/trustdb.c:1618
#, c-format
msgid "key %08lX.%lu: created in future (time warp or clock problem)\n"
msgstr ""
"ËÌÀÞ %08lX.%lu: ÓÇÅÎÅÒÉÒÏ×ÁÎ × ÂÕÄÕÝÅÍ (ÎÅÐÒÁ×ÉÌØÎÏ ÕÓÔÁÎÏ×ÌÅÎÙ ÞÁÓÙ)\n"
-#: g10/trustdb.c:1576
+#: g10/trustdb.c:1625
#, c-format
msgid "key %08lX.%lu: expired at %s\n"
msgstr "ËÌÀÞ %08lX.%lu: ÓÒÏË ÄÅÊÓÔ×ÉÑ ÉÓÔÅË %s\n"
-#: g10/trustdb.c:1584
+#: g10/trustdb.c:1633
#, c-format
msgid "key %08lX.%lu: trust check failed: %s\n"
msgstr "ËÌÀÞ %08lX.%lu: ÐÒÏ×ÅÒËÁ ÄÏ×ÅÒÉÑ ÎÅ ÕÄÁÌÁÓØ: %s\n"
-#: g10/trustdb.c:1753 g10/trustdb.c:1782 g10/trustdb.c:2521
+#: g10/trustdb.c:1820 g10/trustdb.c:1849 g10/trustdb.c:2588
msgid "WARNING: can't yet handle long pref records\n"
msgstr ""
-#: g10/trustdb.c:1804
+#: g10/trustdb.c:1871
#, fuzzy, c-format
msgid "get_dir_record: search_record failed: %s\n"
msgstr "ÏÂÎÏ×ÌÅÎÉÅ ÓÅËÒÅÔÁ ÎÅ ÕÄÁÌÏÓØ: %s\n"
-#: g10/trustdb.c:1867
+#: g10/trustdb.c:1934
#, c-format
msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but marked as checked\n"
msgstr ""
-#: g10/trustdb.c:1871
+#: g10/trustdb.c:1938
#, c-format
msgid "NOTE: sig rec %lu[%d] in hintlist of %lu but not marked\n"
msgstr ""
#. we need the dir record
-#: g10/trustdb.c:1878
+#: g10/trustdb.c:1945
#, c-format
msgid "sig rec %lu[%d] in hintlist of %lu does not point to a dir record\n"
msgstr ""
-#: g10/trustdb.c:1884
+#: g10/trustdb.c:1951
#, c-format
msgid "lid %lu: no primary key\n"
msgstr ""
-#: g10/trustdb.c:1917
+#: g10/trustdb.c:1984
#, fuzzy, c-format
msgid "lid %lu: user id not found in keyblock\n"
msgstr "%s: ÐÏÌØÚÏ×ÁÔÅÌØ ÎÅ ÎÁÊÄÅÎ\n"
-#: g10/trustdb.c:1921
+#: g10/trustdb.c:1988
#, fuzzy, c-format
msgid "lid %lu: user id without signature\n"
msgstr "ËÌÀÞ %08lX: ÎÅÔ ÉÄÅÎÔÉÆÉËÁÔÏÒÁ ÐÏÌØÚÏ×ÁÔÅÌÑ ÄÌÑ ÐÏÄÐÉÓÉ\n"
-#: g10/trustdb.c:1928
+#: g10/trustdb.c:1995
#, fuzzy, c-format
msgid "lid %lu: self-signature in hintlist\n"
msgstr "build_sigrecs: Selbst-Signatur fehlt\n"
-#: g10/trustdb.c:1939 g10/trustdb.c:2658 g10/trustdb.c:2742
+#: g10/trustdb.c:2006 g10/trustdb.c:2725 g10/trustdb.c:2809
#, fuzzy
msgid "Valid certificate revocation"
msgstr "ðÌÏÈÏÊ ÓÅÒÔÉÆÉËÁÔ"
-#: g10/trustdb.c:1940 g10/trustdb.c:2659 g10/trustdb.c:2743
+#: g10/trustdb.c:2007 g10/trustdb.c:2726 g10/trustdb.c:2810
#, fuzzy
msgid "Good certificate"
msgstr "ðÌÏÈÏÊ ÓÅÒÔÉÆÉËÁÔ"
-#: g10/trustdb.c:1949
+#: g10/trustdb.c:2016
msgid "very strange: no public key\n"
msgstr ""
-#: g10/trustdb.c:1997
+#: g10/trustdb.c:2064
#, c-format
msgid "hintlist %lu[%d] of %lu does not point to a dir record\n"
msgstr ""
-#: g10/trustdb.c:2003
+#: g10/trustdb.c:2070
#, c-format
msgid "lid %lu does not have a key\n"
msgstr ""
-#: g10/trustdb.c:2013
+#: g10/trustdb.c:2080
#, fuzzy, c-format
msgid "lid %lu: can't get keyblock: %s\n"
msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÚÁÐÉÓÁÔØ ÂÌÏË ËÌÀÞÁ: %s\n"
-#: g10/trustdb.c:2070 g10/trustdb.c:2984
+#: g10/trustdb.c:2137 g10/trustdb.c:3051
#, fuzzy, c-format
msgid "tdbio_search_dir failed: %s\n"
msgstr "ÏÛÉÂËÁ ÄÅËÏÄÉÒÏ×ÁÎÉÑ: %s\n"
-#: g10/trustdb.c:2223
+#: g10/trustdb.c:2290
#, fuzzy, c-format
msgid "key %08lX.%lu: Good subkey binding\n"
msgstr "ËÌÀÞ %08lX: ÎÅÔ ÉÄÅÎÔÉÆÉËÁÔÏÒÁ ÐÏÌØÚÏ×ÁÔÅÌÑ\n"
-#: g10/trustdb.c:2229 g10/trustdb.c:2271
+#: g10/trustdb.c:2296 g10/trustdb.c:2338
#, fuzzy, c-format
msgid "key %08lX.%lu: Invalid subkey binding: %s\n"
msgstr "ËÌÀÞ %08lX: ÎÅÔ ÄÏÐÕÓÔÉÍÙÈ ÉÄÅÎÔÉÆÉËÁÔÏÒÏ× ÐÏÌØÚÏ×ÁÔÅÌÅÊ\n"
-#: g10/trustdb.c:2244
+#: g10/trustdb.c:2311
#, fuzzy, c-format
msgid "key %08lX.%lu: Valid key revocation\n"
msgstr "ËÌÀÞ %08lX.%lu: ÓÒÏË ÄÅÊÓÔ×ÉÑ ÉÓÔÅË %s\n"
-#: g10/trustdb.c:2250
+#: g10/trustdb.c:2317
#, fuzzy, c-format
msgid "key %08lX.%lu: Invalid key revocation: %s\n"
msgstr "ËÌÀÞ %08lX: ÏÔËÒÙÔÙÊ ËÌÀÞ ÎÅ ÎÁÊÄÅÎ: %s\n"
-#: g10/trustdb.c:2265
+#: g10/trustdb.c:2332
#, fuzzy, c-format
msgid "key %08lX.%lu: Valid subkey revocation\n"
msgstr "ËÌÀÞ %08lX: ÎÅÔ ÄÏÐÕÓÔÉÍÙÈ ÉÄÅÎÔÉÆÉËÁÔÏÒÏ× ÐÏÌØÚÏ×ÁÔÅÌÅÊ\n"
-#: g10/trustdb.c:2365
+#: g10/trustdb.c:2432
#, fuzzy
msgid "Good self-signature"
msgstr "[ÓÁÍÏ-ÐÏÄÐÉÓØ]\n"
-#: g10/trustdb.c:2376
+#: g10/trustdb.c:2443
#, fuzzy
msgid "Invalid self-signature"
msgstr "ËÌÀÞ %08lX: ÎÅÄÏÐÕÓÔÉÍÁÑ ÓÁÍÏ-ÐÏÄÐÉÓØ\n"
-#: g10/trustdb.c:2386
+#: g10/trustdb.c:2453
msgid "Valid user ID revocation skipped due to a newer self signature\n"
msgstr ""
-#: g10/trustdb.c:2393
+#: g10/trustdb.c:2460
#, fuzzy
msgid "Valid user ID revocation\n"
msgstr "îÅÄÏÐÕÓÔÉÍÙÊ ×ÙÂÏÒ.\n"
-#: g10/trustdb.c:2400
+#: g10/trustdb.c:2467
#, fuzzy
msgid "Invalid user ID revocation"
msgstr "îÅÄÏÐÕÓÔÉÍÙÊ ×ÙÂÏÒ.\n"
-#: g10/trustdb.c:2484
+#: g10/trustdb.c:2551
msgid "Too many preferences"
msgstr ""
-#: g10/trustdb.c:2498
+#: g10/trustdb.c:2565
msgid "Too many preference items"
msgstr ""
-#: g10/trustdb.c:2637
+#: g10/trustdb.c:2704
msgid "Duplicated certificate - deleted"
msgstr ""
-#: g10/trustdb.c:2670
+#: g10/trustdb.c:2737
#, fuzzy
msgid "Hmmm, public key lost?"
msgstr "ðÌÏÈÏÊ ÏÔËÒÙÔÙÊ ËÌÀÞ"
-#: g10/trustdb.c:2680 g10/trustdb.c:2763
+#: g10/trustdb.c:2747 g10/trustdb.c:2830
#, fuzzy
msgid "Invalid certificate revocation"
msgstr "ðÌÏÈÏÊ ÓÅÒÔÉÆÉËÁÔ"
-#: g10/trustdb.c:2681 g10/trustdb.c:2764
+#: g10/trustdb.c:2748 g10/trustdb.c:2831
#, fuzzy
msgid "Invalid certificate"
msgstr "ðÌÏÈÏÊ ÓÅÒÔÉÆÉËÁÔ"
-#: g10/trustdb.c:2696
+#: g10/trustdb.c:2763
#, c-format
msgid "uid %08lX.%lu/%02X%02X: has shadow dir %lu but is not yet marked.\n"
msgstr ""
-#: g10/trustdb.c:2710
+#: g10/trustdb.c:2777
#, c-format
msgid "sig record %lu[%d] points to wrong record.\n"
msgstr ""
#. that should never happen
-#: g10/trustdb.c:2954
+#: g10/trustdb.c:3021
#, fuzzy, c-format
msgid "insert_trust_record: keyblock not found: %s\n"
msgstr "ËÌÀÞ %08lX: ÓÅËÒÅÔÎÙÊ ËÌÀÞ ÎÅ ÎÁÊÄÅÎ: %s\n"
-#: g10/trustdb.c:2972
+#: g10/trustdb.c:3039
msgid "did not use primary key for insert_trust_record()\n"
msgstr ""
#: g10/ringedit.c:293
#, fuzzy, c-format
msgid "%s: can't create keyring: %s\n"
msgstr "%s: ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ: %s\n"
#: g10/ringedit.c:299 g10/ringedit.c:1264
#, fuzzy, c-format
msgid "%s: keyring created\n"
msgstr "%s: ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ: %s\n"
#: g10/ringedit.c:1449
msgid "WARNING: 2 files with confidential information exists.\n"
msgstr ""
#: g10/ringedit.c:1450
#, fuzzy, c-format
msgid "%s is the unchanged one\n"
msgstr "éÓÐÏÌØÚÏ×ÁÎ ÎÅÐÒÁ×ÉÌØÎÙÊ ÓÅËÒÅÔÎÙÊ ËÌÀÞ"
#: g10/ringedit.c:1451
#, c-format
msgid "%s is the new one\n"
msgstr ""
#: g10/ringedit.c:1452
msgid "Please fix this possible security flaw\n"
msgstr ""
#: g10/skclist.c:94
#, fuzzy, c-format
msgid "skipped '%s': %s\n"
msgstr "%s: ÐÒÏÐÕÝÅÎ: %s\n"
#: g10/skclist.c:100
#, fuzzy, c-format
msgid ""
"skipped '%s': this is a PGP generated ElGamal key which is not secure for "
"signatures!\n"
msgstr "ÜÔÏÔ ElGamal ËÌÀÞ, ÓÏÚÄÁÎÎÙÊ PGP, ÎÅ ÎÁÄÅÖÅÎ ÄÌÑ ÓÏÚÄÁÎÉÑ ÐÏÄÐÉÓÅÊ!\n"
#. do not overwrite
#: g10/openfile.c:58
#, c-format
msgid "File '%s' exists. "
msgstr "æÁÊÌ '%s' ÓÕÝÅÓÔ×ÕÅÔ. "
#: g10/openfile.c:60
msgid "Overwrite (y/N)? "
msgstr "ðÅÒÅÐÉÓÁÔØ (y/N)? "
#: g10/openfile.c:85
#, fuzzy
msgid "writing to stdout\n"
msgstr "ÚÁÐÉÓÙ×ÁÅÔÓÑ × '%s'\n"
#: g10/openfile.c:134
#, fuzzy, c-format
msgid "assuming signed data in '%s'\n"
msgstr "ÎÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÐÏÄÐÉÓÁÎÎÙÅ ÄÁÎÎÙÅ '%s' .\n"
#: g10/openfile.c:181
#, c-format
msgid "%s: new options file created\n"
msgstr ""
#: g10/encr-data.c:59
#, fuzzy, c-format
msgid "%s encrypted data\n"
msgstr "ÚÁÛÉÆÒÏ×ÁÔØ ÄÁÎÎÙÅ"
#: g10/encr-data.c:61
#, c-format
msgid "encrypted with unknown algorithm %d\n"
msgstr ""
#: g10/encr-data.c:74
#, fuzzy
msgid ""
"WARNING: Message was encrypted with a weak key in the symmetric cipher.\n"
msgstr ""
"ðÒÅÄÕÐÒÅÖÄÅÎÉÅ: ÓÏÏÂÝÅÎÉÅ ÂÙÌÏ ÚÁÛÉÆÒÏ×ÁÎÏ, ÉÓÐÏÌØÚÕÑ ÓÌÁÂÙÊ ËÌÀÞ, × "
"ÓÉÍÍÅÔÒÉÞÎÏÍ ÁÌÇÏÒÉÔÍÅ ÛÉÆÒÏ×ÁÎÉÑ.\n"
#: g10/seskey.c:52
msgid "weak key created - retrying\n"
msgstr "ÐÏÌÕÞÉÌÓÑ ÓÌÁÂÙÊ ËÌÀÞ, ÐÒÏÂÕÅÍ ÅÝÅ ÒÁÚ\n"
#: g10/seskey.c:57
#, c-format
msgid "cannot avoid weak key for symmetric cipher; tried %d times!\n"
msgstr ""
"ÎÅ ÐÏÌÕÞÁÅÔÓÑ ÉÚÂÅÖÁÔØ ÓÌÁÂÏÇÏ ËÌÀÞÁ × ÓÉÍÍÅÔÒÉÞÎÏÍ ÁÌÇÏÒÉÔÍÅ; ÐÒÏÂÏ×ÁÌÉ %d "
"ÒÁÚ!\n"
#. begin of list
-#: g10/helptext.c:45
+#: g10/helptext.c:48
msgid "edit_ownertrust.value"
msgstr ""
-#: g10/helptext.c:51
+#: g10/helptext.c:54
msgid "revoked_key.override"
msgstr ""
-#: g10/helptext.c:55
+#: g10/helptext.c:58
msgid "untrusted_key.override"
msgstr ""
-#: g10/helptext.c:59
+#: g10/helptext.c:62
msgid "pklist.user_id.enter"
msgstr ""
-#: g10/helptext.c:63
+#: g10/helptext.c:66
msgid "keygen.algo"
msgstr ""
-#: g10/helptext.c:79
+#: g10/helptext.c:82
msgid "keygen.algo.elg_se"
msgstr ""
-#: g10/helptext.c:86
+#: g10/helptext.c:89
msgid "keygen.size"
msgstr ""
-#: g10/helptext.c:90
+#: g10/helptext.c:93
msgid "keygen.size.huge.okay"
msgstr ""
-#: g10/helptext.c:95
+#: g10/helptext.c:98
msgid "keygen.size.large.okay"
msgstr ""
-#: g10/helptext.c:100
+#: g10/helptext.c:103
msgid "keygen.valid"
msgstr ""
-#: g10/helptext.c:104
+#: g10/helptext.c:107
msgid "keygen.valid.okay"
msgstr ""
-#: g10/helptext.c:109
+#: g10/helptext.c:112
msgid "keygen.name"
msgstr ""
-#: g10/helptext.c:114
+#: g10/helptext.c:117
msgid "keygen.email"
msgstr ""
-#: g10/helptext.c:118
+#: g10/helptext.c:121
msgid "keygen.comment"
msgstr ""
-#: g10/helptext.c:123
+#: g10/helptext.c:126
msgid "keygen.userid.cmd"
msgstr ""
-#: g10/helptext.c:132
+#: g10/helptext.c:135
msgid "keygen.sub.okay"
msgstr ""
-#: g10/helptext.c:136
+#: g10/helptext.c:139
msgid "sign_uid.okay"
msgstr ""
-#: g10/helptext.c:141
+#: g10/helptext.c:144
msgid "change_passwd.empty.okay"
msgstr ""
-#: g10/helptext.c:146
+#: g10/helptext.c:149
msgid "keyedit.cmd"
msgstr ""
-#: g10/helptext.c:150
+#: g10/helptext.c:153
msgid "keyedit.save.okay"
msgstr ""
-#: g10/helptext.c:155
+#: g10/helptext.c:158
msgid "keyedit.cancel.okay"
msgstr ""
-#: g10/helptext.c:159
+#: g10/helptext.c:162
msgid "keyedit.sign_all.okay"
msgstr ""
-#: g10/helptext.c:163
+#: g10/helptext.c:166
msgid "keyedit.remove.uid.okay"
msgstr ""
-#: g10/helptext.c:168
+#: g10/helptext.c:171
msgid "keyedit.remove.subkey.okay"
msgstr ""
# ################################
# ####### Help msgids ############
# ################################
-#: g10/helptext.c:172
+#: g10/helptext.c:175
msgid "passphrase.enter"
msgstr ""
"Bitte geben Sie die \"Passhrase\" ein; dies ist ein geheimer Satz der aus\n"
"beliebigen Zeichen bestehen kann. Was Sie eingegeben wird nicht angezeigt.\n"
"Zur ihrer eigenen Sicherbeit benutzen Sie biite einen Satz, den sie sich\n"
"gut merken könne, der aber nicht leicht zu raten ist; Zitate und andere\n"
"bekannte Texte sind eine SCHLECHTE Wahl, da diese mit Sicherheit online\n"
"verfügbar sind und durch entsprechende Programme zum Raten der "
"\"Passphrase\"\n"
"benutzt werden. Sätze mit persönlicher Bedeutung, die auch noch durch\n"
"falsche Groß-/Kleinschreibung und eingestreute Sonderzeichen verändert "
"werden,\n"
"sind i.d.R. eine gute Wahl"
-#: g10/helptext.c:179
+#: g10/helptext.c:182
msgid "passphrase.repeat"
msgstr ""
"Um sicher zu gehen, daß Sie sich bei der Eingabe der \"Passphrase\" nicht\n"
"vertippt haben, geben Sie diese bitte nochmal ein. Nur wenn beide Eingaben\n"
"übereinstimmen, wird die \"Passphrase\" akzeptiert."
-#: g10/helptext.c:183
+#: g10/helptext.c:186
#, fuzzy
msgid "detached_signature.filename"
msgstr "ÉÍÑ ÆÁÊÌÁ ÄÌÑ ÏÔÄÅÌØÎÏÊ ÐÏÄÐÉÓÉ"
-#: g10/helptext.c:187
+#: g10/helptext.c:190
msgid "openfile.overwrite.okay"
msgstr "÷Ù ÖÅÌÁÅÔÅ ÐÅÒÅÚÁÐÉÓÁÔØ ÆÁÊÌ (×ÏÚÍÏÖÎÁ ÐÏÔÅÒÑ ÄÁÎÎÙÈ)"
-#: g10/helptext.c:201
+#: g10/helptext.c:204
msgid "No help available"
msgstr "ðÏÍÏÝØ ÏÔÓÕÔÓÔ×ÕÅÔ."
-#: g10/helptext.c:213
+#: g10/helptext.c:216
#, c-format
msgid "No help available for '%s'"
msgstr "ðÏÍÏÝØ ÄÌÑ '%s' ÏÔÓÕÔÓÔ×ÕÅÔ."
#~ msgid "You will see a list of signators etc. here\n"
#~ msgstr "úÄÅÓØ ×Ù Õ×ÉÄÉÔÅ ÓÐÉÓÏË ÐÏÄÐÉÓÁ×ÛÉÈ É Ô.Ä.\n"
#~ msgid "key %08lX: already in ultikey_table\n"
#~ msgstr "ËÌÀÞ %08lX: ÕÖÅ × ultikey_table\n"
#, fuzzy
#~ msgid "key %08lX.%lu, uid %02X%02X: no public key for signature %08lX\n"
#~ msgstr ""
#~ "ËÌÀÞ %08lX.%lu, uid %02X%02X: ÎÅÔ ÏÔËÒÙÔÏÇÏ ËÌÀÞÁ ÄÌÑ ÐÏÄÐÉÓÉ %08lX\n"
#, fuzzy
#~ msgid "key %08lX.%lu, uid %02X%02X: invalid %ssignature: %s\n"
#~ msgstr "ËÌÀÞ %08lX: ÎÅÄÏÐÕÓÔÉÍÁÑ ÓÁÍÏ-ÐÏÄÐÉÓØ\n"
#~ msgid "can't write keyring\n"
#~ msgstr "kann ËÌÀÞring nicht schreiben\n"
#~ msgid "make a signature on a key in the keyring"
#~ msgstr "ËÌÀÞ signieren"
#~ msgid "edit a key signature"
#~ msgstr "Bearbeiten der Signaturen eines ËÌÀÞs"
#~ msgid "do not make any changes"
#~ msgstr "Keine wirklichen Änderungen durchführen"
#~ msgid ""
#~ "It's up to you to assign a value here; this value will never be exported\n"
#~ "to any 3rd party. We need it to implement the web-of-trust; it has nothing\n"
#~ "to do with the (implicitly created) web-of-certificates.\n"
#~ msgstr ""
#~ "Sie müssen selbt entscheiden, welchen Wert Sie hier eintragen; dieser Wert\n"
#~ "wird niemals an eine dritte Seite weitergegeben. Wir brauchen diesen Wert,\n"
#~ "um das \"Netz des Vertrauens\" aufzubauen. Dieses hat nichts mit dem "
#~ "(implizit\n"
#~ "erzeugten) \"Netz der Zertifikate\" zu tun.\n"
#~ msgid "public and secret subkey created.\n"
#~ msgstr "Öffentlicher und privater ËÌÀÞ erzeugt.\n"
#~ msgid "No public key for %d signatures\n"
#~ msgstr "Kein öffentlicher ËÌÀÞ für %d Signaturen\n"
#~ msgid "[User name not available] "
#~ msgstr "[Benuzername nicht verfügbar] "
#~ msgid "This is a BAD signature!\n"
#~ msgstr "Dies ist eine FALSCHE Signatur!\n"
#~ msgid "The signature could not be checked!\n"
#~ msgstr "Die Signatur konnte nicht geprüft werden!\n"
#~ msgid "Checking signatures of this public key certificate:\n"
#~ msgstr "Die Signaturen dieses Zertifikats werden überprüft:\n"
#~ msgid "Do you want to remove some of the invalid signatures? "
#~ msgstr "Möchten Sie einige der ungültigen Signaturen entfernen? "
#~ msgid "there is a secret key for this public key!\n"
#~ msgstr "Es gibt einen privaten ËÌÀÞ zu diesem öffentlichen ËÌÀÞ!\n"
#~ msgid "use option \"--delete-secret-key\" to delete it first.\n"
#~ msgstr ""
#~ "Benutzen Sie das Kommando \"--delete-secret-key\", um ihn vorab zu "
#~ "entfernen.\n"
#~ msgid "can't do that in batchmode without \"--yes\"\n"
#~ msgstr "Dies kann im Batchmodus ohne \"--yes\" nicht durchgeführt werden.\n"
#~ msgid "Delete this key from the keyring? "
#~ msgstr "Diesen ËÌÀÞ aus dem ËÌÀÞring löschen? "
#~ msgid "This is a secret key! - really delete? "
#~ msgstr "Dies ist ein privater ËÌÀÞ! - Wirklich löschen? "
diff --git a/scripts/ChangeLog b/scripts/ChangeLog
index eb1fe5ab2..7151ecaa3 100644
--- a/scripts/ChangeLog
+++ b/scripts/ChangeLog
@@ -1,24 +1,28 @@
+Wed Dec 23 13:18:14 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
+
+ * gnupg.spec: Updated version by Fabio Coatti
+
Thu Dec 17 18:31:15 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* gnupg.spec: New version by Reuben Sumner and did some more
changes.
Fri Nov 27 12:39:29 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* commit: New
Fri Nov 20 12:01:57 1998 Werner Koch (wk@isil.d.shuttle.de)
* mkdiff: signs the patch file
Sat Oct 17 16:10:16 1998 Werner Koch (wk@isil.d.shuttle.de)
* autogen.sh: New.
Wed Oct 14 09:55:25 1998 Werner Koch (wk@isil.d.shuttle.de)
* config.guess (FreeBSD): Changes from Jun Kuriyama to support ELF
* config.sub: (freebsd): Add to maybe_os
diff --git a/scripts/gnupg.spec b/scripts/gnupg.spec
index e2961e50f..34a8c2005 100644
--- a/scripts/gnupg.spec
+++ b/scripts/gnupg.spec
@@ -1,58 +1,84 @@
#
# gnupg -- gnu privacy guard
# This is a template. The dist target uses it to create the real file.
#
%define version @pkg_version@
+%define name gnupg
Summary: GPL public key crypto
-Name: gnupg
+Name: %{name}
Version: %{version}
Release: 1
Copyright: GPL
Group: Applications/Cryptography
-Source: ftp://ftp.gnupg.org/pub/gcrypt/gnupg-%{version}.tar.gz
+Source: ftp://ftp.gnupg.org/pub/gcrypt/%{name}-%{version}.tar.gz
URL: http://www.gnupg.org
Provides: gpg openpgp
-BuildRoot: /tmp/gnupg
+BuildRoot: /tmp/rpmbuild_%{name}
+
+%changelog
+* Sat Dec 19 1998 Fabio Coatti <cova@felix.unife.it>
+- Modified the spec file provided by Caskey L. Dickson <caskey-at-technocage.com>
+- Now it can be built also by non-root. Installation has to be done as
+root, gpg is suid.
+- Added some changes by Ross Golder <rossigee@bigfoot.com>
+- Updates for version 0.4.5 of GnuPG (.mo files)
%description
-GnuPG is a complete and free replacement for PGP. Because it does not use
-IDEA or RSA it can be used without any restrictions. GnuPG is in
+GnuPG is a complete and free replacement for PGP. Because it does not
+use IDEA or RSA it can be used without any restrictions. GnuPG is in
compliance with the OpenPGP specification (RFC2440).
-%prep
-%setup
+%description -l it
+GnuPG è un sostituto completo e gratuito per il PGP. Non utilizzando
+IDEA o RSA può essere utilizzato senza restrizioni. GnuPG è conforme
+alle specifiche OpenPGP (RFC2440).
+%prep
rm -rf $RPM_BUILD_ROOT
+rm -rf $RPM_BUILD_DIR/%{name}-%{version}
+
+%setup
%build
-CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=/usr
+CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=/usr
make
%install
-make prefix="${RPM_BUILD_ROOT}/usr" install
-
-%clean
-rm -rf $RPM_BUILD_ROOT
+make install-strip prefix=$RPM_BUILD_ROOT/usr
+rm $RPM_BUILD_ROOT/usr/man/man1/gpgm.1
+cd $RPM_BUILD_ROOT/usr/man/man1/
+ln -s gpg.1 gpgm.1
%files
-%attr(-,root,root) %doc doc/DETAILS
-%attr(-,root,root) %doc INSTALL
-%attr(-,root,root) %doc AUTHORS
-%attr(-,root,root) %doc ABOUT-NLS
-%attr(-,root,root) %doc COPYING
-%attr(-,root,root) %doc ChangeLog
-%attr(-,root,root) %doc NEWS
-%attr(-,root,root) %doc README
-%attr(-,root,root) %doc THANKS
-%attr(-,root,root) %doc TODO
-%attr(-,root,root) /usr/man/man1/gpg.1
+
+%doc %attr (-,root,root) INSTALL
+%doc %attr (-,root,root) AUTHORS
+%doc %attr (-,root,root) COPYING
+%doc %attr (-,root,root) ChangeLog
+%doc %attr (-,root,root) NEWS
+%doc %attr (-,root,root) README
+%doc %attr (-,root,root) THANKS
+%doc %attr (-,root,root) TODO
+%doc %attr (-,root,root) doc/DETAILS
+%doc %attr (-,root,root) doc/FAQ
+%doc %attr (-,root,root) doc/HACKING
+%doc %attr (-,root,root) doc/OpenPGP
+
+%attr (-,root,root) /usr/man/man1/gpg.1
+%attr (-,root,root) /usr/man/man1/gpgm.1
%attr (4755,root,root) /usr/bin/gpg
%attr (755,root,root) /usr/bin/gpgm
-%attr(-,root,root) /usr/share/locale/en/LC_MESSAGES/gnupg.mo
-%attr(-,root,root) /usr/share/locale/de/LC_MESSAGES/gnupg.mo
-%attr(-,root,root) /usr/share/locale/it/LC_MESSAGES/gnupg.mo
-%attr(-,root,root) /usr/share/locale/fr/LC_MESSAGES/gnupg.mo
-%attr(-,root,root) /usr/lib/gnupg/tiger
-%attr(-,root,root) /usr/lib/gnupg/twofish
-%attr(-,root,root) /usr/share/gnupg/options.skel
+#%attr (-,root,root) /usr/share/locale/en/LC_MESSAGES/%{name}.mo
+%attr (-,root,root) /usr/share/locale/de/LC_MESSAGES/%{name}.mo
+%attr (-,root,root) /usr/share/locale/it/LC_MESSAGES/%{name}.mo
+%attr (-,root,root) /usr/share/locale/fr/LC_MESSAGES/%{name}.mo
+%attr (-,root,root) /usr/share/locale/ru/LC_MESSAGES/%{name}.mo
+%attr (-,root,root) /usr/share/locale/es_ES/LC_MESSAGES/%{name}.mo
+%attr (-,root,root) /usr/share/locale/pt_BR/LC_MESSAGES/%{name}.mo
+%attr (-,root,root) /usr/lib/%{name}
+%attr (-,root,root) /usr/share/%{name}
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+rm -rf $RPM_BUILD_DIR/%{name}-%{version}
diff --git a/tools/bftest.c b/tools/bftest.c
index 551e8e55d..0bfb4105e 100644
--- a/tools/bftest.c
+++ b/tools/bftest.c
@@ -1,112 +1,112 @@
/* bftest.c - Blowfish test program
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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>
#ifdef __MINGW32__
#include <io.h>
#include <fcntl.h>
#endif
#include "util.h"
#include "cipher.h"
#include "i18n.h"
static void
my_usage(void)
{
fprintf(stderr, "usage: bftest [-e][-d] algo key\n");
exit(1);
}
const char *
strusage( int level )
{
return default_strusage(level);
}
static void
i18n_init(void)
{
#ifdef ENABLE_NLS
#ifdef HAVE_LC_MESSAGES
setlocale( LC_MESSAGES, "" );
#else
setlocale( LC_ALL, "" );
#endif
bindtextdomain( PACKAGE, G10_LOCALEDIR );
textdomain( PACKAGE );
#endif
}
int
main(int argc, char **argv)
{
int encode=0;
CIPHER_HANDLE hd;
char buf[4096];
int n, size=4096;
int algo;
#ifdef __MINGW32__
setmode( fileno(stdin), O_BINARY );
setmode( fileno(stdout), O_BINARY );
#endif
i18n_init();
if( argc > 1 && !strcmp(argv[1], "-e") ) {
encode++;
argc--; argv++;
}
else if( argc > 1 && !strcmp(argv[1], "-E") ) {
encode++;
argc--; argv++;
size = 10;
}
else if( argc > 1 && !strcmp(argv[1], "-d") ) {
argc--; argv++;
}
else if( argc > 1 && !strcmp(argv[1], "-D") ) {
argc--; argv++;
size = 10;
}
if( argc != 3 )
my_usage();
argc--; argv++;
algo = string_to_cipher_algo( *argv );
argc--; argv++;
hd = cipher_open( algo, CIPHER_MODE_CFB, 0 );
cipher_setkey( hd, *argv, strlen(*argv) );
cipher_setiv( hd, NULL );
while( (n = fread( buf, 1, size, stdin )) > 0 ) {
if( encode )
cipher_encrypt( hd, buf, buf, n );
else
cipher_decrypt( hd, buf, buf, n );
if( fwrite( buf, 1, n, stdout) != n )
log_fatal("write error\n");
}
cipher_close(hd);
return 0;
}
diff --git a/tools/mpicalc.c b/tools/mpicalc.c
index 3d7ae37ca..22af505ac 100644
--- a/tools/mpicalc.c
+++ b/tools/mpicalc.c
@@ -1,375 +1,375 @@
/* mpitest.c - test the mpi functions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* This is an RPN calculator; values must be given in hex.
* Operation is like dc(1) except that the input/output radix is
* always 16 and you can use a '-' to prefix a negative number.
* Addition operators: ++ and --. All operators must be delimited by a blank
*
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <ctype.h>
#include "util.h"
#include "mpi.h"
#include "i18n.h"
#define STACKSIZE 100
static MPI stack[STACKSIZE];
static int stackidx;
const char *
strusage( int level )
{
const char *p;
switch( level ) {
case 10:
case 0: p = "mpicalc - v" VERSION "; "
"Copyright 1997 Werner Koch (dd9jn)" ; break;
case 13: p = "mpicalc"; break;
case 14: p = VERSION; break;
case 1:
case 11: p = "Usage: mpicalc (-h for help)";
break;
case 2:
case 12: p =
"\nSyntax: mpicalc [options] [files]\n"
"MPI RPN calculator\n";
break;
default: p = default_strusage(level);
}
return p;
}
static void
i18n_init(void)
{
#ifdef ENABLE_NLS
#ifdef HAVE_LC_MESSAGES
setlocale( LC_MESSAGES, "" );
#else
setlocale( LC_ALL, "" );
#endif
bindtextdomain( PACKAGE, G10_LOCALEDIR );
textdomain( PACKAGE );
#endif
}
static void
do_add(void)
{
if( stackidx < 2 ) {
fputs("stack underflow\n",stderr);
return;
}
mpi_add( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
stackidx--;
}
static void
do_sub(void)
{
if( stackidx < 2 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_sub( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
stackidx--;
}
static void
do_inc(void)
{
if( stackidx < 1 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_add_ui( stack[stackidx-1], stack[stackidx-1], 1 );
}
static void
do_dec(void)
{
if( stackidx < 1 ) {
fputs("stack underflow\n", stderr);
return;
}
/* mpi_sub_ui( stack[stackidx-1], stack[stackidx-1], 1 ); */
}
static void
do_mul(void)
{
if( stackidx < 2 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_mul( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
stackidx--;
}
static void
do_div(void)
{
if( stackidx < 2 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_fdiv_q( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
stackidx--;
}
static void
do_rem(void)
{
if( stackidx < 2 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_fdiv_r( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
stackidx--;
}
static void
do_powm(void)
{
MPI a;
if( stackidx < 3 ) {
fputs("stack underflow\n", stderr);
return;
}
a= mpi_alloc(10);
mpi_powm( a, stack[stackidx-3], stack[stackidx-2], stack[stackidx-1] );
mpi_free(stack[stackidx-3]);
stack[stackidx-3] = a;
stackidx -= 2;
}
static void
do_inv(void)
{
MPI a = mpi_alloc(40);
if( stackidx < 2 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_invm( a, stack[stackidx-2], stack[stackidx-1] );
mpi_set(stack[stackidx-2],a);
mpi_free(a);
stackidx--;
}
static void
do_gcd(void)
{
MPI a = mpi_alloc(40);
if( stackidx < 2 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_gcd( a, stack[stackidx-2], stack[stackidx-1] );
mpi_set(stack[stackidx-2],a);
mpi_free(a);
stackidx--;
}
static void
do_rshift(void)
{
if( stackidx < 1 ) {
fputs("stack underflow\n", stderr);
return;
}
mpi_rshift( stack[stackidx-1],stack[stackidx-1], 1 );
}
int
main(int argc, char **argv)
{
static ARGPARSE_OPTS opts[] = {
{0} };
ARGPARSE_ARGS pargs;
int i, c;
int state = 0;
char strbuf[1000];
int stridx=0;
pargs.argc = &argc;
pargs.argv = &argv;
pargs.flags = 0;
i18n_init();
while( arg_parse( &pargs, opts) ) {
switch( pargs.r_opt ) {
default : pargs.err = 2; break;
}
}
if( argc )
usage(1);
for(i=0; i < STACKSIZE; i++ )
stack[i] = NULL;
stackidx =0;
while( (c=getc(stdin)) != EOF ) {
if( !state ) { /* waiting */
if( isdigit(c) || (c >='A' && c <= 'F') ) {
state = 1;
ungetc(c, stdin);
strbuf[0] = '0';
strbuf[1] = 'x';
stridx=2;
}
else if( isspace(c) )
;
else {
switch(c) {
case '+':
if( (c=getc(stdin)) == '+' )
do_inc();
else {
ungetc(c, stdin);
do_add();
}
break;
case '-':
if( (c=getc(stdin)) == '-' )
do_dec();
else if( isdigit(c) || (c >='A' && c <= 'F') ) {
state = 1;
ungetc(c, stdin);
strbuf[0] = '-';
strbuf[1] = '0';
strbuf[2] = 'x';
stridx=3;
}
else {
ungetc(c, stdin);
do_sub();
}
break;
case '*':
do_mul();
break;
case '/':
do_div();
break;
case '%':
do_rem();
break;
case '^':
do_powm();
break;
case 'I':
do_inv();
break;
case 'G':
do_gcd();
break;
case '>':
do_rshift();
break;
case 'i': /* dummy */
if( !stackidx )
fputs("stack underflow\n", stderr);
else {
mpi_free(stack[stackidx-1]);
stackidx--;
}
break;
case 'd': /* duplicate the tos */
if( !stackidx )
fputs("stack underflow\n", stderr);
else if( stackidx < STACKSIZE ) {
mpi_free(stack[stackidx]);
stack[stackidx] = mpi_copy( stack[stackidx-1] );
stackidx++;
}
else
fputs("stack overflow\n", stderr);
break;
case 'c':
for(i=0; i < stackidx; i++ )
mpi_free(stack[i]), stack[i] = NULL;
stackidx = 0;
break;
case 'p': /* print the tos */
if( !stackidx )
puts("stack is empty");
else {
mpi_print(stdout, stack[stackidx-1], 1 );
putchar('\n');
}
break;
case 'f': /* print the stack */
for( i = stackidx-1 ; i >= 0; i-- ) {
printf("[%2d]: ", i );
mpi_print(stdout, stack[i], 1 );
putchar('\n');
}
break;
default:
fputs("invalid operator\n", stderr);
}
}
}
else if( state == 1 ) { /* in a number */
if( !(isdigit(c) || (c >='A' && c <= 'F')) ) { /* store the number */
state = 0;
ungetc(c, stdin);
if( stridx < 1000 )
strbuf[stridx] = 0;
if( stackidx < STACKSIZE ) {
if( !stack[stackidx] )
stack[stackidx] = mpi_alloc(10);
if( mpi_fromstr(stack[stackidx], strbuf) )
fputs("invalid number\n", stderr);
else
stackidx++;
}
else
fputs("stack overflow\n", stderr);
}
else { /* store digit */
if( stridx < 999 )
strbuf[stridx++] = c;
else if( stridx == 999 ) {
strbuf[stridx] = 0;
fputs("string too large - truncated\n", stderr);
stridx++;
}
}
}
}
for(i=0; i < stackidx; i++ )
mpi_free(stack[i]);
return 0;
}
diff --git a/util/dotlock.c b/util/dotlock.c
index b57583004..794a362f7 100644
--- a/util/dotlock.c
+++ b/util/dotlock.c
@@ -1,239 +1,239 @@
/* dotlock.c - dotfile locking
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "types.h"
#include "util.h"
#include "memory.h"
static int read_lockfile( const char *name );
/****************
* Create a lockfile with the given name. A TIMEOUT of 0
* returns immediately, -1 waits forever (hopefully not), other
* values are timeouts in milliseconds.
* Returns: a char pointer used as handle for release lock
* or NULL in case of an error.
*
* Notes: This function creates a lock file in the same directory
* as file_to_lock with the name "file_to_lock.lock"
* A temporary file ".#lk.<hostname>.pid[.threadid] is used.
* This function does nothing for Windoze.
*/
const char *
make_dotlock( const char *file_to_lock, long timeout )
{
int fd=-1, pid;
char pidstr[16];
const char *handle = NULL;
char *lockname = NULL;
char *tname = NULL;
int have_tfile = 0;
struct utsname uts;
const char *dirpart;
int dirpartlen;
sprintf( pidstr, "%10d\n", getpid() );
/* fixme: add the hostname to the second line (FQDN or IP addr?) */
/* create a temporary file */
#if SYS_NMLN < 8
#error Aiiih
#endif
if( uname( &uts ) )
strcpy( uts.nodename, "unknown" );
if( !(dirpart = strrchr( file_to_lock, '/' )) ) {
dirpart = ".";
dirpartlen = 1;
}
else {
dirpartlen = dirpart - file_to_lock;
dirpart = file_to_lock;
}
#ifdef _THREAD_SAFE
tname = m_alloc( dirpartlen + 6 + strlen(uts.nodename) + 11+ 20 );
sprintf( tname, "%.*s/.#lk.%s.%d.%p",
dirpartlen, dirpart, uts.nodename, getpid(), &pid );
#else
tname = m_alloc( dirpartlen + 6 + strlen(uts.nodename) + 11 );
sprintf( tname, "%.*s/.#lk.%s.%d",
dirpartlen, dirpart, uts.nodename, getpid() );
#endif
do {
errno = 0;
fd = open( tname, O_WRONLY|O_CREAT|O_EXCL,
S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
} while( fd == -1 && errno == EINTR );
if( fd == -1 ) {
log_error( "failed to create temporary file '%s': %s\n",
tname, strerror(errno));
goto leave;
}
have_tfile = 1;
if( write(fd, pidstr, 11 ) != 11 ) {
log_fatal( "error writing to '%s': %s\n", tname, strerror(errno) );
goto leave;
}
if( close(fd) ) {
log_error( "error closing '%s': %s\n", tname, strerror(errno));
goto leave;
}
fd = -1;
lockname = m_alloc( strlen(file_to_lock) + 6 );
strcpy(stpcpy(lockname, file_to_lock), ".lock");
retry:
if( !link(tname, lockname) ) {/* fixme: better use stat to check the link count */
handle = lockname;
lockname = NULL;
}
else if( errno == EEXIST ) {
if( (pid = read_lockfile(lockname)) == -1 ) {
if( errno == ENOENT ) {
log_info( "lockfile disappeared\n");
goto retry;
}
log_info("cannot read lockfile\n");
}
else if( pid == getpid() ) {
log_info( "Oops: lock already hold by us\n");
handle = lockname;
lockname = NULL;
}
#if 0 /* we should not do this without checking the permissions */
/* and the hostname */
else if( kill(pid, 0) && errno == ESRCH ) {
log_info( "removing stale lockfile (created by %d)", pid );
remove( lockname );
goto retry;
}
#endif
if( timeout == -1 ) {
struct timeval tv;
log_info( "waiting for lock (hold by %d) ...\n", pid );
/* can't use sleep, cause signals may be blocked */
tv.tv_sec = 1;
tv.tv_usec = 0;
select(0, NULL, NULL, NULL, &tv);
goto retry;
}
/* fixme: implement timeouts */
}
else
log_error( "lock not made: link() failed: %s\n", strerror(errno) );
leave:
if( fd != -1 )
close(fd);
if( have_tfile )
remove(tname);
m_free(tname);
m_free(lockname);
return handle;
}
/****************
* Create a lockfile for a existing file
* Returns: a char pointer used as handle for release lock
* or NULL in case of an error.
*
* Notes: This function creates a lock file in the same directory
* as file_to_lock with the name "lock.<inode-no>"
*
* int
* make_inodelock( const char *file_to_lock )
*
*/
/****************
* release a lock
* Returns: 0 := success
*/
int
release_dotlock( const char *lockfile )
{
int pid = read_lockfile( lockfile );
if( pid == -1 ) {
log_error( "release_dotlock: lockfile error");
return -1;
}
if( pid != getpid() ) {
log_error( "release_dotlock: not our lock (pid=%d)", pid);
return -1;
}
if( remove( lockfile ) ) {
log_error( "release_dotlock: error removing lockfile '%s'",
lockfile);
return -1;
}
m_free( (char*)lockfile );
return 0;
}
/****************
* Read the lock file and return the pid, returns -1 on error.
*/
static int
read_lockfile( const char *name )
{
int fd, pid;
char pidstr[16];
if( (fd = open(name, O_RDONLY)) == -1 ) {
int e = errno;
log_debug("error opening lockfile '%s': %s\n", name, strerror(errno) );
errno = e;
return -1;
}
if( read(fd, pidstr, 10 ) != 10 ) {
log_debug("error reading lockfile '%s'", name );
close(fd);
errno = 0;
return -1;
}
close(fd);
pid = atoi(pidstr);
if( !pid || pid == -1 ) {
log_error("invalid pid %d in lockfile '%s'", pid, name );
errno = 0;
return -1;
}
return pid;
}
diff --git a/util/errors.c b/util/errors.c
index b4db10b17..acee8f14b 100644
--- a/util/errors.c
+++ b/util/errors.c
@@ -1,102 +1,102 @@
/* errors.c - error strings
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <stdarg.h>
#include "errors.h"
#include "i18n.h"
#ifndef HAVE_STRERROR
char *
strerror( int n )
{
extern char *sys_errlist[];
extern int sys_nerr;
static char buf[15];
if( n >= 0 && n < sys_nerr )
return sys_errlist[n];
strcpy( buf, "Unknown error" );
return buf;
}
#endif /* !HAVE_STRERROR */
const char *
g10_errstr( int err )
{
static char buf[50];
const char *p;
#define X(n,s) case G10ERR_##n : p = s; break;
switch( err ) {
case -1: p = "eof"; break;
case 0: p = "okay"; break;
X(GENERAL, N_("General error"))
X(UNKNOWN_PACKET, N_("Unknown packet type"))
X(UNKNOWN_VERSION,N_("Unknown version"))
X(PUBKEY_ALGO ,N_("Unknown pubkey algorithm"))
X(DIGEST_ALGO ,N_("Unknown digest algorithm"))
X(BAD_PUBKEY ,N_("Bad public key"))
X(BAD_SECKEY ,N_("Bad secret key"))
X(BAD_SIGN ,N_("Bad signature"))
X(CHECKSUM , N_("Checksum error"))
X(BAD_PASS , N_("Bad passphrase"))
X(NO_PUBKEY ,N_("Public key not found"))
X(CIPHER_ALGO ,N_("Unknown cipher algorithm"))
X(KEYRING_OPEN ,N_("Can't open the keyring"))
X(INVALID_PACKET ,N_("Invalid packet"))
X(INVALID_ARMOR ,N_("Invalid armor"))
X(NO_USER_ID ,N_("No such user id"))
X(NO_SECKEY ,N_("Secret key not available"))
X(WRONG_SECKEY ,N_("Wrong secret key used"))
X(UNSUPPORTED ,N_("Not supported"))
X(BAD_KEY ,N_("Bad key"))
X(READ_FILE ,N_("File read error"))
X(WRITE_FILE ,N_("File write error"))
X(COMPR_ALGO ,N_("Unknown compress algorithm"))
X(OPEN_FILE ,N_("File open error"))
X(CREATE_FILE ,N_("File create error"))
X(PASSPHRASE ,N_("Invalid passphrase"))
X(NI_PUBKEY ,N_("Unimplemented pubkey algorithm"))
X(NI_CIPHER ,N_("Unimplemented cipher algorithm"))
X(SIG_CLASS ,N_("Unknown signature class"))
X(TRUSTDB ,N_("Trust database error"))
X(BAD_MPI ,N_("Bad MPI"))
X(RESOURCE_LIMIT ,N_("Resource limit"))
X(INV_KEYRING ,N_("Invalid keyring"))
X(BAD_CERT ,N_("Bad certificate"))
X(INV_USER_ID ,N_("Malformed user id"))
X(CLOSE_FILE ,N_("File close error"))
X(RENAME_FILE ,N_("File rename error"))
X(DELETE_FILE ,N_("File delete error"))
X(UNEXPECTED ,N_("Unexpected data"))
X(TIME_CONFLICT ,N_("Timestamp conflict"))
X(WR_PUBKEY_ALGO ,N_("Unusable pubkey algorithm"))
X(FILE_EXISTS ,N_("File exists"))
X(WEAK_KEY ,N_("Weak key"))
default: p = buf; sprintf(buf, "g10err=%d", err); break;
}
#undef X
return _(p);
}
diff --git a/util/fileutil.c b/util/fileutil.c
index 2169f9572..adf5c7a5d 100644
--- a/util/fileutil.c
+++ b/util/fileutil.c
@@ -1,158 +1,158 @@
/* fileutil.c - file utilities
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <stdarg.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include "util.h"
#include "memory.h"
#include "ttyio.h"
/***************
* Extract from a given path the filename component.
*
*/
char *
make_basename(const char *filepath)
{
char *p;
if ( !(p=strrchr(filepath, '/')) )
#ifdef __MINGW32__
if ( !(p=strrchr(filepath, '\\')) )
if ( !(p=strrchr(filepath, ':')) )
#endif
{
return m_strdup(filepath);
}
return m_strdup(p+1);
}
/***************
* Extract from a given filename the path prepended to it.
* If their isn't a path prepended to the filename, a dot
* is returned ('.').
*
*/
char *
make_dirname(const char *filepath)
{
char *dirname;
int dirname_length;
char *p;
if ( !(p=strrchr(filepath, '/')) )
#ifdef __MINGW32__
if ( !(p=strrchr(filepath, '\\')) )
if ( !(p=strrchr(filepath, ':')) )
#endif
{
return m_strdup(".");
}
dirname_length = p-filepath;
dirname = m_alloc(dirname_length+1);
strncpy(dirname, filepath, dirname_length);
dirname[dirname_length] = 0;
return dirname;
}
/****************
* Construct a filename from the NULL terminated list of parts.
* Tilde expansion is done here.
*/
char *
make_filename( const char *first_part, ... )
{
va_list arg_ptr ;
size_t n;
const char *s;
char *name, *home, *p;
va_start( arg_ptr, first_part ) ;
n = strlen(first_part)+1;
while( (s=va_arg(arg_ptr, const char *)) )
n += strlen(s) + 1;
va_end(arg_ptr);
home = NULL;
if( *first_part == '~' && first_part[1] == '/'
&& (home = getenv("HOME")) && *home )
n += strlen(home);
name = m_alloc(n);
p = home ? stpcpy(stpcpy(name,home), first_part+1)
: stpcpy(name, first_part);
va_start( arg_ptr, first_part ) ;
while( (s=va_arg(arg_ptr, const char *)) )
p = stpcpy(stpcpy(p,"/"), s);
va_end(arg_ptr);
return name;
}
int
compare_filenames( const char *a, const char *b )
{
/* ? check whether this is an absolute filename and
* resolve symlinks?
*/
#ifdef __MINGW32__
return stricmp(a,b);
#else
return strcmp(a,b);
#endif
}
/****************
* A simple function to decide whether the filename is stdout
* or a real filename.
*/
const char *
print_fname_stdout( const char *s )
{
if( !s || (*s == '-' && !s[1]) )
return "[stdout]";
return s;
}
const char *
print_fname_stdin( const char *s )
{
if( !s || (*s == '-' && !s[1]) )
return "[stdin]";
return s;
}
diff --git a/util/g10u.c b/util/g10u.c
index e63b8f7ca..967ba089a 100644
--- a/util/g10u.c
+++ b/util/g10u.c
@@ -1,39 +1,39 @@
/* g10u.c - Wrapper for utility functions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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"
#define _g10lib_INTERNAL 1
#include "g10lib.h"
const char *g10u_revision_string(int dummy) { return "$Revision$"; }
void *g10_malloc( size_t n ) { return m_alloc( n ); }
void *g10_calloc( size_t n ) { return m_alloc_clear( n ); }
void *g10_malloc_secure( size_t n ) { return m_alloc_secure( n ); }
void *g10_calloc_secure( size_t n ) { return m_alloc_secure_clear( n ); }
void *g10_realloc( void *a, size_t n ) { return m_realloc( a, n ); }
void g10_free( void *p ) { m_free( p ); }
char *g10_strdup( const char * a) { return m_strdup( a ); }
diff --git a/util/iobuf.c b/util/iobuf.c
index 67a097495..7ed5b722d 100644
--- a/util/iobuf.c
+++ b/util/iobuf.c
@@ -1,1309 +1,1309 @@
/* iobuf.c - file handling
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "memory.h"
#include "util.h"
#include "iobuf.h"
typedef struct {
FILE *fp; /* open file handle */
int print_only_name; /* flags indicating that fname is not a real file*/
char fname[1]; /* name of the file */
} file_filter_ctx_t ;
/* The first partial length header block must be of size 512
* to make it easier (and efficienter) we use a min. block size of 512
* for all chznks (but the last one) */
#define OP_MIN_PARTIAL_CHUNK 512
#define OP_MIN_PARTIAL_CHUNK_2POW 9
typedef struct {
int usage;
size_t size;
size_t count;
int partial; /* 1 = partial header, 2 in last partial packet */
char *buffer; /* used for partial header */
size_t buflen; /* used size of buffer */
int first_c; /* of partial header (which is > 0)*/
int eof;
} block_filter_ctx_t;
static int underflow(IOBUF a);
static const char *get_real_fname( IOBUF a );
/****************
* Read data from a file into buf which has an allocated length of *LEN.
* return the number of read bytes in *LEN. OPAQUE is the FILE * of
* the stream. A is not used.
* control may be:
* IOBUFCTRL_INIT: called just before the function is linked into the
* list of function. This can be used to prepare internal
* data structures of the function.
* IOBUFCTRL_FREE: called just before the function is removed from the
* list of functions and can be used to release internal
* data structures or close a file etc.
* IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer
* with new stuff. *RET_LEN is the available size of the
* buffer, and should be set to the number of bytes
* which were put into the buffer. The function
* returns 0 to indicate success, -1 on EOF and
* G10ERR_xxxxx for other errors.
*
* IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff.
* *RET_LAN is the number of bytes in BUF.
*
*/
static int
file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
{
file_filter_ctx_t *a = opaque;
FILE *fp = a->fp;
size_t size = *ret_len;
size_t nbytes = 0;
int c, rc = 0;
char *p;
if( control == IOBUFCTRL_UNDERFLOW ) {
assert( size ); /* need a buffer */
for(; size; size-- ) {
if( (c=getc(fp)) == EOF ) {
if( ferror(fp) ) {
log_error("%s: read error: %s\n",
a->fname, strerror(errno));
rc = G10ERR_READ_FILE;
}
else if( !nbytes )
rc = -1; /* okay: we can return EOF now. */
break;
}
buf[nbytes++] = c & 0xff;
}
*ret_len = nbytes;
}
else if( control == IOBUFCTRL_FLUSH ) {
for(p=buf; nbytes < size; nbytes++, p++ ) {
if( putc(*p, fp) == EOF ) {
log_error("%s: write error: %s\n",
a->fname, strerror(errno));
rc = G10ERR_WRITE_FILE;
break;
}
}
*ret_len = nbytes;
}
else if( control == IOBUFCTRL_INIT ) {
}
else if( control == IOBUFCTRL_DESC ) {
*(char**)buf = "file_filter";
}
else if( control == IOBUFCTRL_FREE ) {
if( fp != stdin && fp != stdout )
fclose(fp);
fp = NULL;
m_free(a); /* we can free our context now */
}
return rc;
}
/****************
* This is used to implement the block write mode.
* Block reading is done on a byte by byte basis in readbyte(),
* without a filter
*/
static int
block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
{
block_filter_ctx_t *a = opaque;
size_t size = *ret_len;
int c, rc = 0;
char *p;
if( control == IOBUFCTRL_UNDERFLOW ) {
size_t n=0;
p = buf;
assert( size ); /* need a buffer */
if( a->eof ) /* don't read any further */
rc = -1;
while( !rc && size ) {
if( !a->size ) { /* get the length bytes */
if( a->partial == 2 ) {
a->eof = 1;
if( !n )
rc = -1;
break;
}
else if( a->partial ) {
/* These OpenPGP introduced huffman encoded length
* bytes are really a mess :-( */
if( a->first_c ) {
c = a->first_c;
a->first_c = 0;
assert( c >= 224 && c < 255 );
}
else if( (c = iobuf_get(chain)) == -1 ) {
log_error("block_filter: 1st length byte missing\n");
rc = G10ERR_READ_FILE;
break;
}
if( c < 192 ) {
a->size = c;
a->partial = 2;
if( !a->size ) {
a->eof = 1;
if( !n )
rc = -1;
break;
}
}
else if( c < 224 ) {
a->size = (c - 192) * 256;
if( (c = iobuf_get(chain)) == -1 ) {
log_error("block_filter: 2nd length byte missing\n");
rc = G10ERR_READ_FILE;
break;
}
a->size += c + 192;
a->partial = 2;
if( !a->size ) {
a->eof = 1;
if( !n )
rc = -1;
break;
}
}
else if( c == 255 ) {
a->size = iobuf_get(chain) << 24;
a->size |= iobuf_get(chain) << 16;
a->size |= iobuf_get(chain) << 8;
if( (c = iobuf_get(chain)) == -1 ) {
log_error("block_filter: invalid 4 byte length\n");
rc = G10ERR_READ_FILE;
break;
}
a->size |= c;
}
else { /* next partial body length */
a->size = 1 << (c & 0x1f);
}
}
else { /* the gnupg partial length scheme - much better :-) */
c = iobuf_get(chain);
a->size = c << 8;
c = iobuf_get(chain);
a->size |= c;
if( c == -1 ) {
log_error("block_filter: error reading length info\n");
rc = G10ERR_READ_FILE;
}
if( !a->size ) {
a->eof = 1;
if( !n )
rc = -1;
break;
}
}
}
for(; !rc && size && a->size; size--, a->size-- ) {
if( (c=iobuf_get(chain)) == -1 ) {
log_error("block_filter %p: read error (size=%lu,a->size=%lu)\n",
a, (ulong)size, (ulong)a->size);
rc = G10ERR_READ_FILE;
}
else {
*p++ = c;
n++;
}
}
}
*ret_len = n;
}
else if( control == IOBUFCTRL_FLUSH ) {
if( a->partial ) { /* the complicated openpgp scheme */
size_t blen, n, nbytes = size + a->buflen;
assert( a->buflen <= OP_MIN_PARTIAL_CHUNK );
if( nbytes < OP_MIN_PARTIAL_CHUNK ) {
/* not enough to write a partial block out , so we store it*/
if( !a->buffer )
a->buffer = m_alloc( OP_MIN_PARTIAL_CHUNK );
memcpy( a->buffer + a->buflen, buf, size );
a->buflen += size;
}
else { /* okay, we can write out something */
/* do this in a loop to use the most efficient block lengths */
p = buf;
do {
/* find the best matching block length - this is limited
* by the size of the internal buffering */
for( blen=OP_MIN_PARTIAL_CHUNK*2,
c=OP_MIN_PARTIAL_CHUNK_2POW+1; blen < nbytes;
blen *=2, c++ )
;
blen /= 2; c--;
/* write the partial length header */
assert( c <= 0x1f ); /*;-)*/
c |= 0xe0;
iobuf_put( chain, c );
if( (n=a->buflen) ) { /* write stuff from the buffer */
assert( n == OP_MIN_PARTIAL_CHUNK);
if( iobuf_write(chain, a->buffer, n ) )
rc = G10ERR_WRITE_FILE;
a->buflen = 0;
nbytes -= n;
}
if( (n = nbytes) > blen )
n = blen;
if( n && iobuf_write(chain, p, n ) )
rc = G10ERR_WRITE_FILE;
p += n;
nbytes -= n;
} while( !rc && nbytes >= OP_MIN_PARTIAL_CHUNK );
/* store the rest in the buffer */
if( !rc && nbytes ) {
assert( !a->buflen );
assert( nbytes < OP_MIN_PARTIAL_CHUNK );
if( !a->buffer )
a->buffer = m_alloc( OP_MIN_PARTIAL_CHUNK );
memcpy( a->buffer, p, nbytes );
a->buflen = nbytes;
}
}
}
else { /* the gnupg scheme */
size_t avail, n;
for(p=buf; !rc && size; ) {
n = size;
avail = a->size - a->count;
if( !avail ) {
if( n > a->size ) {
iobuf_put( chain, (a->size >> 8) & 0xff );
iobuf_put( chain, a->size & 0xff );
avail = a->size;
a->count = 0;
}
else {
iobuf_put( chain, (n >> 8) & 0xff );
iobuf_put( chain, n & 0xff );
avail = n;
a->count = a->size - n;
}
}
if( n > avail )
n = avail;
if( iobuf_write(chain, p, n ) )
rc = G10ERR_WRITE_FILE;
a->count += n;
p += n;
size -= n;
}
}
}
else if( control == IOBUFCTRL_INIT ) {
if( DBG_IOBUF )
log_debug("init block_filter %p\n", a );
if( a->partial )
a->count = 0;
else if( a->usage == 1 )
a->count = a->size = 0;
else
a->count = a->size; /* force first length bytes */
a->eof = 0;
a->buffer = NULL;
a->buflen = 0;
}
else if( control == IOBUFCTRL_DESC ) {
*(char**)buf = "block_filter";
}
else if( control == IOBUFCTRL_FREE ) {
if( a->usage == 2 ) { /* write the end markers */
if( a->partial ) {
u32 len;
/* write out the remaining bytes without a partial header
* the length of this header may be 0 - but if it is
* the first block we are not allowed to use a partial header
* and frankly we can't do so, because this length must be
* a power of 2. This is _really_ complicated because we
* have to check the possible length of a packet prior
* to it's creation: a chein of filters becomes complicated
* and we need a lot of code to handle compressed packets etc.
* :-(((((((
*/
/* construct header */
len = a->buflen;
if( len < 192 )
rc = iobuf_put(chain, len );
else if( len < 8384 ) {
if( !(rc=iobuf_put( chain, ((len-192) / 256) + 192)) )
rc = iobuf_put( chain, ((len-192) % 256));
}
else { /* use a 4 byte header */
if( !(rc=iobuf_put( chain, 0xff )) )
if( !(rc=iobuf_put( chain, (len >> 24)&0xff )) )
if( !(rc=iobuf_put( chain, (len >> 16)&0xff )) )
if( !(rc=iobuf_put( chain, (len >> 8)&0xff )))
rc=iobuf_put( chain, len & 0xff );
}
if( !rc && len )
rc = iobuf_write(chain, a->buffer, len );
if( rc ) {
log_error("block_filter: write error: %s\n",strerror(errno));
rc = G10ERR_WRITE_FILE;
}
m_free( a->buffer ); a->buffer = NULL; a->buflen = 0;
}
else {
iobuf_writebyte(chain, 0);
iobuf_writebyte(chain, 0);
}
}
else if( a->size ) {
log_error("block_filter: pending bytes!\n");
}
if( DBG_IOBUF )
log_debug("free block_filter %p\n", a );
m_free(a); /* we can free our context now */
}
return rc;
}
/****************
* Allocate a new io buffer, with no function assigned.
* Usage is the desired usage: 1 for input, 2 for output, 3 for temp buffer
* BUFSIZE is a suggested buffer size.
*/
IOBUF
iobuf_alloc(int usage, size_t bufsize)
{
IOBUF a;
static int number=0;
a = m_alloc_clear(sizeof *a);
a->usage = usage;
a->d.buf = m_alloc( bufsize );
a->d.size = bufsize;
a->no = ++number;
a->subno = 0;
a->opaque = NULL;
return a;
}
int
iobuf_close( IOBUF a )
{
IOBUF a2;
size_t dummy_len;
int rc=0;
if( a && a->directfp ) {
fclose( a->directfp );
if( DBG_IOBUF )
log_debug("iobuf-close -> %p\n", a->directfp );
return 0;
}
for( ; a && !rc ; a = a2 ) {
a2 = a->chain;
if( a->usage == 2 && (rc=iobuf_flush(a)) )
log_error("iobuf_flush failed on close: %s\n", g10_errstr(rc));
if( DBG_IOBUF )
log_debug("iobuf-%d.%d: close '%s'\n", a->no, a->subno, a->desc );
if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE,
a->chain, NULL, &dummy_len)) )
log_error("IOBUFCTRL_FREE failed on close: %s\n", g10_errstr(rc) );
m_free(a->d.buf);
m_free(a);
}
return rc;
}
int
iobuf_cancel( IOBUF a )
{
const char *s;
if( a && a->usage == 2 ) {
s = get_real_fname(a);
if( s && *s )
remove(s); /* remove the file. Fixme: this will fail for MSDOZE*/
} /* because the file is still open */
return iobuf_close(a);
}
/****************
* create a temporary iobuf, which can be used to collect stuff
* in an iobuf and later be written by iobuf_write_temp() to another
* iobuf.
*/
IOBUF
iobuf_temp()
{
IOBUF a;
a = iobuf_alloc(3, 8192 );
return a;
}
IOBUF
iobuf_temp_with_content( const char *buffer, size_t length )
{
IOBUF a;
a = iobuf_alloc(3, length );
memcpy( a->d.buf, buffer, length );
a->d.len = length;
return a;
}
/****************
* Create a head iobuf for reading from a file
* returns: NULL if an error occures and sets errno
*/
IOBUF
iobuf_open( const char *fname )
{
IOBUF a;
FILE *fp;
file_filter_ctx_t *fcx;
size_t len;
int print_only = 0;
if( !fname || (*fname=='-' && !fname[1]) ) {
fp = stdin; /* fixme: set binary mode for msdoze */
fname = "[stdin]";
print_only = 1;
}
else if( !(fp = fopen(fname, "rb")) )
return NULL;
a = iobuf_alloc(1, 8192 );
fcx = m_alloc( sizeof *fcx + strlen(fname) );
fcx->fp = fp;
fcx->print_only_name = print_only;
strcpy(fcx->fname, fname );
a->filter = file_filter;
a->filter_ov = fcx;
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
if( DBG_IOBUF )
log_debug("iobuf-%d.%d: open '%s'\n", a->no, a->subno, fname );
return a;
}
/****************
* create an iobuf for writing to a file; the file will be created.
*/
IOBUF
iobuf_create( const char *fname )
{
IOBUF a;
FILE *fp;
file_filter_ctx_t *fcx;
size_t len;
int print_only = 0;
if( !fname || (*fname=='-' && !fname[1]) ) {
fp = stdout;
fname = "[stdout]";
print_only = 1;
}
else if( !(fp = fopen(fname, "wb")) )
return NULL;
a = iobuf_alloc(2, 8192 );
fcx = m_alloc( sizeof *fcx + strlen(fname) );
fcx->fp = fp;
fcx->print_only_name = print_only;
strcpy(fcx->fname, fname );
a->filter = file_filter;
a->filter_ov = fcx;
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
if( DBG_IOBUF )
log_debug("iobuf-%d.%d: create '%s'\n", a->no, a->subno, a->desc );
return a;
}
/****************
* append to an iobuf; if the file does not exist, create it.
* cannot be used for stdout.
*/
IOBUF
iobuf_append( const char *fname )
{
IOBUF a;
FILE *fp;
file_filter_ctx_t *fcx;
size_t len;
if( !fname )
return NULL;
else if( !(fp = fopen(fname, "ab")) )
return NULL;
a = iobuf_alloc(2, 8192 );
fcx = m_alloc( sizeof *fcx + strlen(fname) );
fcx->fp = fp;
strcpy(fcx->fname, fname );
a->filter = file_filter;
a->filter_ov = fcx;
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
if( DBG_IOBUF )
log_debug("iobuf-%d.%d: append '%s'\n", a->no, a->subno, a->desc );
return a;
}
IOBUF
iobuf_openrw( const char *fname )
{
IOBUF a;
FILE *fp;
file_filter_ctx_t *fcx;
size_t len;
if( !fname )
return NULL;
else if( !(fp = fopen(fname, "r+b")) )
return NULL;
a = iobuf_alloc(2, 8192 );
fcx = m_alloc( sizeof *fcx + strlen(fname) );
fcx->fp = fp;
strcpy(fcx->fname, fname );
a->filter = file_filter;
a->filter_ov = fcx;
file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
if( DBG_IOBUF )
log_debug("iobuf-%d.%d: openrw '%s'\n", a->no, a->subno, a->desc );
return a;
}
/****************
* You can overwrite the normal iobuf behaviour by using this function.
* If used the iobuf is a simple wrapper around stdio.
* NULL if an error occures and sets errno
*/
IOBUF
iobuf_fopen( const char *fname, const char *mode )
{
IOBUF a;
FILE *fp;
int print_only = 0;
if( !fname || (*fname=='-' && !fname[1]) ) {
fp = stdin; /* fixme: set binary mode for msdoze */
fname = "[stdin]";
print_only = 1;
}
else if( !(fp = fopen(fname, mode) ) )
return NULL;
a = iobuf_alloc(1, 8192 );
a->directfp = fp;
if( DBG_IOBUF )
log_debug("iobuf_fopen -> %p\n", a->directfp );
return a;
}
/****************
* Register an i/o filter.
*/
int
iobuf_push_filter( IOBUF a,
int (*f)(void *opaque, int control,
IOBUF chain, byte *buf, size_t *len), void *ov )
{
IOBUF b;
size_t dummy_len=0;
int rc=0;
if( a->directfp )
BUG();
if( a->usage == 2 && (rc=iobuf_flush(a)) )
return rc;
/* make a copy of the current stream, so that
* A is the new stream and B the original one.
* The contents of the buffers are transferred to the
* new stream.
*/
b = m_alloc(sizeof *b);
memcpy(b, a, sizeof *b );
/* remove the filter stuff from the new stream */
a->filter = NULL;
a->filter_ov = NULL;
a->filter_eof = 0;
if( a->usage == 2 ) { /* allocate a fresh buffer for the original stream */
b->d.buf = m_alloc( a->d.size );
b->d.len = 0;
b->d.start = 0;
}
else { /* allocate a fresh buffer for the new stream */
a->d.buf = m_alloc( a->d.size );
a->d.len = 0;
a->d.start = 0;
}
/* disable nlimit for the new stream */
a->ntotal = b->ntotal + b->nbytes;
a->nlimit = a->nbytes = 0;
a->nofast &= ~1;
/* make a link from the new stream to the original stream */
a->chain = b;
a->opaque = b->opaque;
/* setup the function on the new stream */
a->filter = f;
a->filter_ov = ov;
a->subno = b->subno + 1;
f( ov, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &dummy_len );
if( DBG_IOBUF ) {
log_debug("iobuf-%d.%d: push '%s'\n", a->no, a->subno, a->desc );
for(b=a; b; b = b->chain )
log_debug("\tchain: %d.%d '%s'\n", b->no, b->subno, b->desc );
}
/* now we can initialize the new function if we have one */
if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_INIT, a->chain,
NULL, &dummy_len)) )
log_error("IOBUFCTRL_INIT failed: %s\n", g10_errstr(rc) );
return rc;
}
/****************
* Remove an i/o filter.
*/
int
iobuf_pop_filter( IOBUF a, int (*f)(void *opaque, int control,
IOBUF chain, byte *buf, size_t *len), void *ov )
{
IOBUF b;
size_t dummy_len=0;
int rc=0;
if( a->directfp )
BUG();
if( DBG_IOBUF )
log_debug("iobuf-%d.%d: pop '%s'\n", a->no, a->subno, a->desc );
if( !a->filter ) { /* this is simple */
b = a->chain;
assert(b);
m_free(a->d.buf);
memcpy(a,b, sizeof *a);
m_free(b);
return 0;
}
for(b=a ; b; b = b->chain )
if( b->filter == f && (!ov || b->filter_ov == ov) )
break;
if( !b )
log_bug("iobuf_pop_filter(): filter function not found\n");
/* flush this stream if it is an output stream */
if( a->usage == 2 && (rc=iobuf_flush(b)) ) {
log_error("iobuf_flush failed in pop_filter: %s\n", g10_errstr(rc));
return rc;
}
/* and tell the filter to free it self */
if( b->filter && (rc = b->filter(b->filter_ov, IOBUFCTRL_FREE, b->chain,
NULL, &dummy_len)) ) {
log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
return rc;
}
/* and see how to remove it */
if( a == b && !b->chain )
log_bug("can't remove the last filter from the chain\n");
else if( a == b ) { /* remove the first iobuf from the chain */
/* everything from b is copied to a. This is save because
* a flush has been done on the to be removed entry
*/
b = a->chain;
m_free(a->d.buf);
memcpy(a,b, sizeof *a);
m_free(b);
if( DBG_IOBUF )
log_debug("iobuf-%d.%d: popped filter\n", a->no, a->subno );
}
else if( !b->chain ) { /* remove the last iobuf from the chain */
log_bug("Ohh jeee, trying to remove a head filter\n");
}
else { /* remove an intermediate iobuf from the chain */
log_bug("Ohh jeee, trying to remove an intermediate filter\n");
}
return rc;
}
/****************
* read underflow: read more bytes into the buffer and return
* the first byte or -1 on EOF.
*/
static int
underflow(IOBUF a)
{
size_t len;
int rc;
/*log_debug("iobuf-%d.%d: underflow: start=%lu len=%lu\n",
a->no, a->subno, (ulong)a->d.start, (ulong)a->d.len );*/
assert( a->d.start == a->d.len );
if( a->usage == 3 )
return -1; /* EOF because a temp buffer can't do an underflow */
if( a->filter_eof ) {
if( DBG_IOBUF )
log_debug("iobuf-%d.%d: filter eof\n", a->no, a->subno );
return -1;
}
if( a->error ) {
if( DBG_IOBUF )
log_debug("iobuf-%d.%d: error\n", a->no, a->subno );
return -1;
}
if( a->directfp ) {
FILE *fp = a->directfp;
len = fread( a->d.buf, 1, a->d.size, fp);
if( len < a->d.size ) {
if( ferror(fp) )
a->error = 1;
else if( feof( fp ) )
a->filter_eof = 1;
}
a->d.len = len;
a->d.start = 0;
return len? a->d.buf[a->d.start++] : -1;
}
if( a->filter ) {
len = a->d.size;
rc = a->filter( a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
a->d.buf, &len );
if( a->usage == 1 && rc == -1 ) { /* EOF: we can remove the filter */
size_t dummy_len;
/* and tell the filter to free it self */
if( a->filter != file_filter ) {
if( (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE, a->chain,
NULL, &dummy_len)) )
log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
a->filter = NULL;
a->desc = NULL;
a->filter_ov = NULL;
}
a->filter_eof = 1;
}
else if( rc )
a->error = 1;
if( !len )
return -1;
a->d.len = len;
a->d.start = 0;
return a->d.buf[a->d.start++];
}
else
return -1; /* no filter; return EOF */
}
void
iobuf_clear_eof(IOBUF a)
{
if( a->directfp )
return;
assert(a->usage == 1);
if( a->filter )
log_info("iobuf-%d.%d: clear_eof '%s' with enabled filter\n", a->no, a->subno, a->desc );
if( !a->filter_eof )
log_info("iobuf-%d.%d: clear_eof '%s' with no EOF pending\n", a->no, a->subno, a->desc );
iobuf_pop_filter(a, NULL, NULL);
}
int
iobuf_flush(IOBUF a)
{
size_t len;
int rc;
if( a->directfp )
return 0;
/*log_debug("iobuf-%d.%d: flush\n", a->no, a->subno );*/
if( a->usage == 3 ) { /* must increase the size of the temp buffer */
char *newbuf;
size_t newsize = a->d.size + 8192;
log_debug("increasing temp iobuf from %lu to %lu\n",
(ulong)a->d.size, (ulong)newsize );
newbuf = m_alloc( newsize );
memcpy( newbuf, a->d.buf, a->d.len );
m_free(a->d.buf);
a->d.buf = newbuf;
a->d.size = newsize;
return 0;
}
else if( a->usage != 2 )
log_bug("flush on non-output iobuf\n");
else if( !a->filter )
log_bug("iobuf_flush: no filter\n");
len = a->d.len;
rc = a->filter( a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len );
if( !rc && len != a->d.len ) {
log_info("iobuf_flush did not write all!\n");
rc = G10ERR_WRITE_FILE;
}
else if( rc )
a->error = 1;
a->d.len = 0;
return rc;
}
/****************
* Read a byte from the iobuf; returns -1 on EOF
*/
int
iobuf_readbyte(IOBUF a)
{
int c;
/* nlimit does not work together with unget */
/* nbytes is also not valid! */
if( a->unget.buf ) {
if( a->unget.start < a->unget.len )
return a->unget.buf[a->unget.start++];
m_free(a->unget.buf);
a->unget.buf = NULL;
a->nofast &= ~2;
}
if( a->nlimit && a->nbytes >= a->nlimit )
return -1; /* forced EOF */
if( a->d.start < a->d.len ) {
c = a->d.buf[a->d.start++];
}
else if( (c=underflow(a)) == -1 )
return -1; /* EOF */
a->nbytes++;
return c;
}
int
iobuf_read(IOBUF a, byte *buf, unsigned buflen )
{
int c, n;
if( a->unget.buf || a->nlimit ) {
/* handle special cases */
for(n=0 ; n < buflen; n++, buf++ ) {
if( (c = iobuf_readbyte(a)) == -1 ) {
if( !n )
return -1; /* eof */
break;
}
else
*buf = c;
}
return n;
}
n = 0;
do {
for( ; n < buflen && a->d.start < a->d.len; n++ )
*buf++ = a->d.buf[a->d.start++];
if( n < buflen ) {
if( (c=underflow(a)) == -1 ) {
a->nbytes += n;
return n? n : -1/*EOF*/;
}
*buf++ = c; n++;
}
} while( n < buflen );
a->nbytes += n;
return n;
}
/****************
* Have a look at the iobuf.
* NOTE: This only works in special cases.
*/
int
iobuf_peek(IOBUF a, byte *buf, unsigned buflen )
{
int n=0;
if( a->filter_eof )
return -1;
if( !(a->d.start < a->d.len) ) {
if( underflow(a) == -1 )
return -1;
/* and unget this character */
assert(a->d.start == 1);
a->d.start = 0;
}
for(n=0 ; n < buflen && (a->d.start+n) < a->d.len ; n++, buf++ )
*buf = a->d.buf[n];
return n;
}
int
iobuf_writebyte(IOBUF a, unsigned c)
{
if( a->directfp )
BUG();
if( a->d.len == a->d.size )
if( iobuf_flush(a) )
return -1;
assert( a->d.len < a->d.size );
a->d.buf[a->d.len++] = c;
return 0;
}
int
iobuf_write(IOBUF a, byte *buf, unsigned buflen )
{
if( a->directfp )
BUG();
do {
for( ; buflen && a->d.len < a->d.size; buflen--, buf++ )
a->d.buf[a->d.len++] = *buf;
if( buflen ) {
if( iobuf_flush(a) )
return -1;
}
} while( buflen );
return 0;
}
int
iobuf_writestr(IOBUF a, const char *buf )
{
for( ; *buf; buf++ )
if( iobuf_writebyte(a, *buf) )
return -1;
return 0;
}
/****************
* copy the contents of TEMP to A.
*/
int
iobuf_write_temp( IOBUF a, IOBUF temp )
{
return iobuf_write(a, temp->d.buf, temp->d.len );
}
/****************
* copy the contents of the temp io stream to BUFFER.
*/
size_t
iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen )
{
size_t n = a->d.len;
if( n > buflen )
n = buflen;
memcpy( buffer, a->d.buf, n );
return n;
}
/****************
* unget the contents of the temp io stream to A and close temp
* Could be optimized!!
*/
void
iobuf_unget_and_close_temp( IOBUF a, IOBUF temp )
{
if( a->unget.buf ) {
if( a->unget.start < a->unget.len )
log_fatal("cannot do any more ungets on this buffer\n");
/* not yet cleaned up; do it now */
m_free(a->unget.buf);
a->unget.buf = NULL;
a->nofast &= ~2;
}
a->unget.size = temp->d.len;
a->unget.buf = m_alloc( a->unget.size );
a->nofast |= 2;
a->unget.len = temp->d.len;
memcpy( a->unget.buf, temp->d.buf, a->unget.len );
iobuf_close(temp);
}
/****************
* Set a limit on how many bytes may be read from the input stream A.
* Setting the limit to 0 disables this feature.
*/
void
iobuf_set_limit( IOBUF a, unsigned long nlimit )
{
if( nlimit )
a->nofast |= 1;
else
a->nofast &= ~1;
a->nlimit = nlimit;
a->ntotal += a->nbytes;
a->nbytes = 0;
}
/****************
* Return the length of an open file
*/
u32
iobuf_get_filelength( IOBUF a )
{
struct stat st;
if( a->directfp ) {
FILE *fp = a->directfp;
if( !fstat(fileno(fp), &st) )
return st.st_size;
log_error("fstat() failed: %s\n", strerror(errno) );
return 0;
}
for( ; a; a = a->chain )
if( !a->chain && a->filter == file_filter ) {
file_filter_ctx_t *b = a->filter_ov;
FILE *fp = b->fp;
if( !fstat(fileno(fp), &st) )
return st.st_size;
log_error("fstat() failed: %s\n", strerror(errno) );
break;
}
return 0;
}
/****************
* Tell the file position, where the next read will take place
*/
ulong
iobuf_tell( IOBUF a )
{
return a->ntotal + a->nbytes;
}
/****************
* This is a very limited implementation. It simply discards all internal
* buffering and removes all filters but the first one.
*/
int
iobuf_seek( IOBUF a, ulong newpos )
{
file_filter_ctx_t *b = NULL;
if( a->directfp ) {
FILE *fp = a->directfp;
if( fseek( fp, newpos, SEEK_SET ) ) {
log_error("can't seek to %lu: %s\n", newpos, strerror(errno) );
return -1;
}
clearerr(fp);
}
else {
for( ; a; a = a->chain ) {
if( !a->chain && a->filter == file_filter ) {
b = a->filter_ov;
break;
}
}
if( !a )
return -1;
if( fseek( b->fp, newpos, SEEK_SET ) ) {
log_error("can't seek to %lu: %s\n", newpos, strerror(errno) );
return -1;
}
}
a->d.len = 0; /* discard buffer */
a->d.start = 0;
a->nbytes = 0;
a->nlimit = 0;
a->nofast &= ~1;
a->ntotal = newpos;
a->error = 0;
/* remove filters, but the last */
while( a->chain )
iobuf_pop_filter( a, a->filter, NULL );
return 0;
}
/****************
* Retrieve the real filename
*/
static const char *
get_real_fname( IOBUF a )
{
for( ; a; a = a->chain )
if( !a->chain && a->filter == file_filter ) {
file_filter_ctx_t *b = a->filter_ov;
return b->print_only_name? NULL : b->fname;
}
return NULL;
}
/****************
* Retrieve the filename
*/
const char *
iobuf_get_fname( IOBUF a )
{
for( ; a; a = a->chain )
if( !a->chain && a->filter == file_filter ) {
file_filter_ctx_t *b = a->filter_ov;
return b->fname;
}
return NULL;
}
/****************
* Start the block write mode, see rfc1991.new for details.
* A value of 0 for N stops this mode (flushes and writes
* the end marker)
*/
void
iobuf_set_block_mode( IOBUF a, size_t n )
{
block_filter_ctx_t *ctx = m_alloc_clear( sizeof *ctx );
assert( a->usage == 1 || a->usage == 2 );
ctx->usage = a->usage;
if( !n ) {
iobuf_pop_filter(a, block_filter, NULL );
}
else {
ctx->size = n; /* only needed for usage 2 */
iobuf_push_filter(a, block_filter, ctx );
}
}
/****************
* enable partial block mode as described in the OpenPGP draft.
* LEN is the first length byte on read, but ignored on writes.
*/
void
iobuf_set_partial_block_mode( IOBUF a, size_t len )
{
block_filter_ctx_t *ctx = m_alloc_clear( sizeof *ctx );
assert( a->usage == 1 || a->usage == 2 );
ctx->usage = a->usage;
if( !len ) {
iobuf_pop_filter(a, block_filter, NULL );
}
else {
ctx->partial = 1;
ctx->size = 0;
ctx->first_c = len;
iobuf_push_filter(a, block_filter, ctx );
}
}
/****************
* Checks whether the stream is in block mode
* Note: This does not work if other filters are pushed on the stream.
*/
int
iobuf_in_block_mode( IOBUF a )
{
if( a && a->filter == block_filter )
return 1; /* yes */
return 0; /* no */
}
diff --git a/util/logger.c b/util/logger.c
index cd9380d01..89302161e 100644
--- a/util/logger.c
+++ b/util/logger.c
@@ -1,231 +1,231 @@
/* logger.c - log functions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <stdarg.h>
#include "util.h"
#include "i18n.h"
static char pidstring[15];
static char *pgm_name;
static int errorcount;
void
log_set_name( const char *name )
{
m_free(pgm_name);
if( name )
pgm_name = m_strdup(name);
else
pgm_name = NULL;
}
const char *
log_get_name(void)
{
return pgm_name? pgm_name : "";
}
void
log_set_pid( int pid )
{
if( pid )
sprintf(pidstring,"[%u]", (unsigned)pid );
else
*pidstring = 0;
}
int
log_get_errorcount( int clear)
{
int n = errorcount;
if( clear )
errorcount = 0;
return n;
}
static void
print_prefix(const char *text)
{
if( pgm_name )
fprintf(stderr, "%s%s: %s", pgm_name, pidstring, text );
else
fprintf(stderr, "?%s: %s", pidstring, text );
}
static void
print_prefix_f(const char *text, const char *fname)
{
if( pgm_name )
fprintf(stderr, "%s%s:%s: %s", pgm_name, pidstring, fname, text );
else
fprintf(stderr, "?%s:%s: %s", pidstring, fname, text );
}
void
g10_log_info( const char *fmt, ... )
{
va_list arg_ptr ;
print_prefix("");
va_start( arg_ptr, fmt ) ;
vfprintf(stderr,fmt,arg_ptr) ;
va_end(arg_ptr);
}
void
g10_log_info_f( const char *fname, const char *fmt, ... )
{
va_list arg_ptr ;
print_prefix_f("", fname);
va_start( arg_ptr, fmt ) ;
vfprintf(stderr,fmt,arg_ptr) ;
va_end(arg_ptr);
}
void
g10_log_error( const char *fmt, ... )
{
va_list arg_ptr ;
print_prefix("");
va_start( arg_ptr, fmt ) ;
vfprintf(stderr,fmt,arg_ptr) ;
va_end(arg_ptr);
errorcount++;
}
void
g10_log_error_f( const char *fname, const char *fmt, ... )
{
va_list arg_ptr ;
print_prefix_f("", fname);
va_start( arg_ptr, fmt ) ;
vfprintf(stderr,fmt,arg_ptr) ;
va_end(arg_ptr);
errorcount++;
}
void
g10_log_fatal( const char *fmt, ... )
{
va_list arg_ptr ;
print_prefix("fatal: ");
va_start( arg_ptr, fmt ) ;
vfprintf(stderr,fmt,arg_ptr) ;
va_end(arg_ptr);
secmem_dump_stats();
exit(2);
}
void
g10_log_fatal_f( const char *fname, const char *fmt, ... )
{
va_list arg_ptr ;
print_prefix_f("fatal: ", fname);
va_start( arg_ptr, fmt ) ;
vfprintf(stderr,fmt,arg_ptr) ;
va_end(arg_ptr);
secmem_dump_stats();
exit(2);
}
void
g10_log_bug( const char *fmt, ... )
{
va_list arg_ptr ;
putc('\n', stderr );
print_prefix("Ohhhh jeeee: ");
va_start( arg_ptr, fmt ) ;
vfprintf(stderr,fmt,arg_ptr) ;
va_end(arg_ptr);
fflush(stderr);
secmem_dump_stats();
abort();
}
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
void
g10_log_bug0( const char *file, int line, const char *func )
{
log_bug(_("... this is a bug (%s:%d:%s)\n"), file, line, func );
}
#else
void
g10_log_bug0( const char *file, int line )
{
log_bug(_("you found a bug ... (%s:%d)\n"), file, line);
}
#endif
void
g10_log_debug( const char *fmt, ... )
{
va_list arg_ptr ;
print_prefix("DBG: ");
va_start( arg_ptr, fmt ) ;
vfprintf(stderr,fmt,arg_ptr) ;
va_end(arg_ptr);
}
void
g10_log_debug_f( const char *fname, const char *fmt, ... )
{
va_list arg_ptr ;
print_prefix_f("DBG: ", fname);
va_start( arg_ptr, fmt ) ;
vfprintf(stderr,fmt,arg_ptr) ;
va_end(arg_ptr);
}
void
g10_log_hexdump( const char *text, char *buf, size_t len )
{
int i;
print_prefix(text);
for(i=0; i < len; i++ )
fprintf(stderr, " %02X", ((byte*)buf)[i] );
fputc('\n', stderr);
}
void
g10_log_mpidump( const char *text, MPI a )
{
print_prefix(text);
mpi_print(stderr, a, 1 );
fputc('\n', stderr);
}
diff --git a/util/memory.c b/util/memory.c
index 586a744ec..4370c72ec 100644
--- a/util/memory.c
+++ b/util/memory.c
@@ -1,589 +1,589 @@
/* memory.c - memory allocation
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* We use our own memory allocation functions instead of plain malloc(),
* so that we can provide some special enhancements:
* a) functions to provide memory from a secure memory.
* b) by looking at the requested allocation size we
* can reuse memory very quickly (e.g. MPI storage)
* (really needed?)
* c) memory usage reporting if compiled with M_DEBUG
* d) memory checking if compiled with M_GUARD
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <stdarg.h>
#include "types.h"
#include "memory.h"
#include "util.h"
#define MAGIC_NOR_BYTE 0x55
#define MAGIC_SEC_BYTE 0xcc
#define MAGIC_END_BYTE 0xaa
#if SIZEOF_UNSIGNED_LONG == 8
#define EXTRA_ALIGN 4
#else
#define EXTRA_ALIGN 0
#endif
const void membug( const char *fmt, ... );
#ifdef M_DEBUG
#ifndef M_GUARD
#define M_GUARD 1
#endif
#undef m_alloc
#undef m_alloc_clear
#undef m_alloc_secure
#undef m_alloc_secure_clear
#undef m_realloc
#undef m_free
#undef m_check
#undef m_strdup
#define FNAME(a) m_debug_ ##a
#define FNAMEPRT , const char *info
#define FNAMEARG , info
#define store_len(p,n,m) do { add_entry(p,n,m, \
info, __FUNCTION__); } while(0)
#else
#define FNAME(a) m_ ##a
#define FNAMEPRT
#define FNAMEARG
#define store_len(p,n,m) do { ((byte*)p)[EXTRA_ALIGN+0] = n; \
((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ; \
((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ; \
((byte*)p)[EXTRA_ALIGN+3] = m? MAGIC_SEC_BYTE \
: MAGIC_NOR_BYTE; \
} while(0)
#endif
#ifdef M_GUARD
static long used_memory;
#endif
#ifdef M_DEBUG /* stuff used for memory debuging */
struct info_entry {
struct info_entry *next;
unsigned count; /* call count */
const char *info; /* the reference to the info string */
};
struct memtbl_entry {
const void *user_p; /* for reference: the pointer given to the user */
size_t user_n; /* length requested by the user */
struct memtbl_entry *next; /* to build a list of unused entries */
const struct info_entry *info; /* points into the table with */
/* the info strings */
unsigned inuse:1; /* this entry is in use */
unsigned count:31;
};
#define INFO_BUCKETS 53
#define info_hash(p) ( *(u32*)((p)) % INFO_BUCKETS )
static struct info_entry *info_strings[INFO_BUCKETS]; /* hash table */
static struct memtbl_entry *memtbl; /* the table with the memory info */
static unsigned memtbl_size; /* number of allocated entries */
static unsigned memtbl_len; /* number of used entries */
static struct memtbl_entry *memtbl_unused;/* to keep track of unused entries */
static void dump_table_at_exit(void);
static void dump_table(void);
static void check_allmem( const char *info );
/****************
* Put the new P into the debug table and return a pointer to the table entry.
* mode is true for security. BY is the name of the function which called us.
*/
static void
add_entry( byte *p, unsigned n, int mode, const char *info, const char *by )
{
unsigned index;
struct memtbl_entry *e;
struct info_entry *ie;
if( memtbl_len < memtbl_size )
index = memtbl_len++;
else {
struct memtbl_entry *e;
/* look for a used entry in the table. We take the first one,
* so that freed entries remain as long as possible in the table
* (free appends a new one)
*/
if( (e = memtbl_unused) ) {
index = e - memtbl;
memtbl_unused = e->next;
e->next = NULL;
}
else { /* no free entries in the table: extend the table */
if( !memtbl_size ) { /* first time */
memtbl_size = 100;
if( !(memtbl = calloc( memtbl_size, sizeof *memtbl )) )
membug("memory debug table malloc failed\n");
index = 0;
memtbl_len = 1;
atexit( dump_table_at_exit );
}
else { /* realloc */
unsigned n = memtbl_size / 4; /* enlarge by 25% */
if(!(memtbl = realloc(memtbl, (memtbl_size+n)*sizeof *memtbl)))
membug("memory debug table realloc failed\n");
memset(memtbl+memtbl_size, 0, n*sizeof *memtbl );
memtbl_size += n;
index = memtbl_len++;
}
}
}
e = memtbl+index;
if( e->inuse )
membug("Ooops: entry %u is flagged as in use\n", index);
e->user_p = p + 4;
e->user_n = n;
e->count++;
if( e->next )
membug("Ooops: entry is in free entry list\n");
/* do we already have this info string */
for( ie = info_strings[info_hash(info)]; ie; ie = ie->next )
if( ie->info == info )
break;
if( !ie ) { /* no: make a new entry */
if( !(ie = malloc( sizeof *ie )) )
membug("can't allocate info entry\n");
ie->next = info_strings[info_hash(info)];
info_strings[info_hash(info)] = ie;
ie->info = info;
ie->count = 0;
}
ie->count++;
e->info = ie;
e->inuse = 1;
/* put the index at the start of the memory */
p[0] = index;
p[1] = index >> 8 ;
p[2] = index >> 16 ;
p[3] = mode? MAGIC_SEC_BYTE : MAGIC_NOR_BYTE ;
if( DBG_MEMORY )
log_debug( "%s allocates %u bytes using %s\n", info, e->user_n, by );
}
/****************
* Check that the memory block is correct. The magic byte has already been
* checked. Checks which are done here:
* - see whether the index points into our memory table
* - see whether P is the same as the one stored in the table
* - see whether we have already freed this block.
*/
struct memtbl_entry *
check_mem( const byte *p, const char *info )
{
unsigned n;
struct memtbl_entry *e;
n = p[EXTRA_ALIGN+0];
n |= p[EXTRA_ALIGN+1] << 8;
n |= p[EXTRA_ALIGN+2] << 16;
if( n >= memtbl_len )
membug("memory at %p corrupted: index=%u table_len=%u (%s)\n",
p+EXTRA_ALIGN+4, n, memtbl_len, info );
e = memtbl+n;
if( e->user_p != p+EXTRA_ALIGN+4 )
membug("memory at %p corrupted: reference mismatch (%s)\n",
p+EXTRA_ALIGN+4, info );
if( !e->inuse )
membug("memory at %p corrupted: marked as free (%s)\n",
p+EXTRA_ALIGN+4, info );
if( !(p[EXTRA_ALIGN+3] == MAGIC_NOR_BYTE
|| p[EXTRA_ALIGN+3] == MAGIC_SEC_BYTE) )
membug("memory at %p corrupted: underflow=%02x (%s)\n",
p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+3], info );
if( p[EXTRA_ALIGN+4+e->user_n] != MAGIC_END_BYTE )
membug("memory at %p corrupted: overflow=%02x (%s)\n",
p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+4+e->user_n], info );
return e;
}
/****************
* free the entry and the memory (replaces free)
*/
static void
free_entry( byte *p, const char *info )
{
struct memtbl_entry *e, *e2;
check_allmem("add_entry");
e = check_mem(p, info);
if( DBG_MEMORY )
log_debug( "%s frees %u bytes alloced by %s\n",
info, e->user_n, e->info->info );
if( !e->inuse ) {
if( e->user_p == p + EXTRA_ALIGN+ 4 )
membug("freeing an already freed pointer at %p\n", p+EXTRA_ALIGN+4 );
else
membug("freeing pointer %p which is flagged as freed\n", p+EXTRA_ALIGN+4 );
}
e->inuse = 0;
e->next = NULL;
if( !memtbl_unused )
memtbl_unused = e;
else {
for(e2=memtbl_unused; e2->next; e2 = e2->next )
;
e2->next = e;
}
memset(p,'f', e->user_n+5);
free(p);
}
static void
dump_entry(struct memtbl_entry *e )
{
unsigned n = e - memtbl;
fprintf(stderr, "mem %4u%c %5u %p %5u %s (%u)\n",
n, e->inuse?'a':'u', e->count, e->user_p, e->user_n,
e->info->info, e->info->count );
}
static void
dump_table_at_exit( void)
{
if( DBG_MEMSTAT )
dump_table();
}
static void
dump_table( void)
{
unsigned n;
struct memtbl_entry *e;
ulong sum = 0, chunks =0;
for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
if(e->inuse) {
dump_entry(e);
sum += e->user_n;
chunks++;
}
}
fprintf(stderr, " memory used: %8lu bytes in %ld chunks\n",
sum, chunks );
}
static void
check_allmem( const char *info )
{
unsigned n;
struct memtbl_entry *e;
for( e = memtbl, n = 0; n < memtbl_len; n++, e++ )
if( e->inuse )
check_mem(e->user_p-4-EXTRA_ALIGN, info);
}
#endif /* M_DEBUG */
const void
membug( const char *fmt, ... )
{
va_list arg_ptr ;
fprintf(stderr, "\nMemory Error: " ) ;
va_start( arg_ptr, fmt ) ;
vfprintf(stderr,fmt,arg_ptr) ;
va_end(arg_ptr);
fflush(stderr);
#ifdef M_DEBUG
if( DBG_MEMSTAT )
dump_table();
#endif
abort();
}
void
m_print_stats( const char *prefix )
{
#ifdef M_DEBUG
unsigned n;
struct memtbl_entry *e;
ulong sum = 0, chunks =0;
for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
if(e->inuse) {
sum += e->user_n;
chunks++;
}
}
log_debug( "%s%smemstat: %8lu bytes in %ld chunks used\n",
prefix? prefix:"", prefix? ": ":"", sum, chunks );
#elif defined(M_GUARD)
log_debug( "%s%smemstat: %8ld bytes\n",
prefix? prefix:"", prefix? ": ":"", used_memory );
#endif
}
void
m_dump_table( const char *prefix )
{
#if M_DEBUG
fprintf(stderr,"Memory-Table-Dump: %s\n", prefix);
dump_table();
#endif
m_print_stats( prefix );
}
static void
out_of_core(size_t n, int secure)
{
log_fatal("out of %s memory while allocating %u bytes\n",
secure? "secure":"" ,(unsigned)n );
}
/****************
* Allocate memory of size n.
* This function gives up if we do not have enough memory
*/
void *
FNAME(alloc)( size_t n FNAMEPRT )
{
char *p;
#ifdef M_GUARD
if( !(p = malloc( n + EXTRA_ALIGN+5 )) )
out_of_core(n,0);
store_len(p,n,0);
used_memory += n;
p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
return p+EXTRA_ALIGN+4;
#else
if( !(p = malloc( n )) )
out_of_core(n,0);
return p;
#endif
}
/****************
* Allocate memory of size n from the secure memory pool.
* This function gives up if we do not have enough memory
*/
void *
FNAME(alloc_secure)( size_t n FNAMEPRT )
{
char *p;
#ifdef M_GUARD
if( !(p = secmem_malloc( n +EXTRA_ALIGN+ 5 )) )
out_of_core(n,1);
store_len(p,n,1);
p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
return p+EXTRA_ALIGN+4;
#else
if( !(p = secmem_malloc( n )) )
out_of_core(n,1);
return p;
#endif
}
void *
FNAME(alloc_clear)( size_t n FNAMEPRT )
{
void *p;
p = FNAME(alloc)( n FNAMEARG );
memset(p, 0, n );
return p;
}
void *
FNAME(alloc_secure_clear)( size_t n FNAMEPRT)
{
void *p;
p = FNAME(alloc_secure)( n FNAMEARG );
memset(p, 0, n );
return p;
}
/****************
* realloc and clear the old space
*/
void *
FNAME(realloc)( void *a, size_t n FNAMEPRT )
{
#ifdef M_GUARD
unsigned char *p = a;
void *b;
size_t len = m_size(a);
if( len >= n ) /* we don't shrink for now */
return a;
if( p[-1] == MAGIC_SEC_BYTE )
b = FNAME(alloc_secure_clear)(n FNAMEARG);
else
b = FNAME(alloc_clear)(n FNAMEARG);
FNAME(check)(NULL FNAMEARG);
memcpy(b, a, len );
FNAME(free)(p FNAMEARG);
#else
void *b;
if( m_is_secure(a) ) {
if( !(b = secmem_realloc( a, n )) )
out_of_core(n,1);
}
else {
if( !(b = realloc( a, n )) )
out_of_core(n,0);
}
#endif
return b;
}
/****************
* Free a pointer
*/
void
FNAME(free)( void *a FNAMEPRT )
{
byte *p = a;
if( !p )
return;
#ifdef M_DEBUG
free_entry(p-EXTRA_ALIGN-4, info);
#elif M_GUARD
m_check(p);
if( m_is_secure(a) )
secmem_free(p-EXTRA_ALIGN-4);
else {
used_memory -= m_size(a);
free(p-EXTRA_ALIGN-4);
}
#else
if( m_is_secure(a) )
secmem_free(p);
else
free(p);
#endif
}
void
FNAME(check)( const void *a FNAMEPRT )
{
#ifdef M_GUARD
const byte *p = a;
#ifdef M_DEBUG
if( p )
check_mem(p-EXTRA_ALIGN-4, info);
else
check_allmem(info);
#else
if( !p )
return;
if( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) )
membug("memory at %p corrupted (underflow=%02x)\n", p, p[-1] );
else if( p[m_size(p)] != MAGIC_END_BYTE )
membug("memory at %p corrupted (overflow=%02x)\n", p, p[-1] );
#endif
#endif
}
size_t
m_size( const void *a )
{
#ifndef M_GUARD
log_debug("Ooops, m_size called\n");
return 0;
#else
const byte *p = a;
size_t n;
#ifdef M_DEBUG
n = check_mem(p-EXTRA_ALIGN-4, "m_size")->user_n;
#else
n = ((byte*)p)[-4];
n |= ((byte*)p)[-3] << 8;
n |= ((byte*)p)[-2] << 16;
#endif
return n;
#endif
}
#if 0 /* not used */
/****************
* Make a copy of the memory block at a
*/
void *
FNAME(copy)( const void *a FNAMEPRT )
{
void *b;
size_t n;
if( !a )
return NULL;
n = m_size(a); Aiiiih woher nehmen
if( m_is_secure(a) )
b = FNAME(alloc_secure)(n FNAMEARG);
else
b = FNAME(alloc)(n FNAMEARG);
memcpy(b, a, n );
return b;
}
#endif
char *
FNAME(strdup)( const char *a FNAMEPRT )
{
size_t n = strlen(a);
char *p = FNAME(alloc)(n+1 FNAMEARG);
strcpy(p, a);
return p;
}
diff --git a/util/miscutil.c b/util/miscutil.c
index 3e382ead9..5e1844893 100644
--- a/util/miscutil.c
+++ b/util/miscutil.c
@@ -1,153 +1,153 @@
/* miscutil.c - miscellaneous utilities
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <string.h>
#include <time.h>
#include <ctype.h>
#include "types.h"
#include "util.h"
#include "i18n.h"
u32
make_timestamp()
{
return time(NULL);
}
u32
add_days_to_timestamp( u32 stamp, u16 days )
{
return stamp + days*86400L;
}
/****************
* Return a string with a time value in the form: x Y, n D, n H
*/
const char *
strtimevalue( u32 value )
{
static char buffer[30];
unsigned int years, days, hours, minutes;
value /= 60;
minutes = value % 60;
value /= 60;
hours = value % 24;
value /= 24;
days = value % 365;
value /= 365;
years = value;
sprintf(buffer,"%uy%ud%uh%um", years, days, hours, minutes );
if( years )
return buffer;
if( days )
return strchr( buffer, 'y' ) + 1;
return strchr( buffer, 'd' ) + 1;
}
/****************
* Note: this function returns GMT
*/
const char *
strtimestamp( u32 stamp )
{
static char buffer[11+5];
struct tm *tp;
time_t atime = stamp;
tp = gmtime( &atime );
sprintf(buffer,"%04d-%02d-%02d",
1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
return buffer;
}
/****************
* Note: this function returns local time
*/
const char *
asctimestamp( u32 stamp )
{
static char buffer[50];
struct tm *tp;
time_t atime = stamp;
tp = localtime( &atime );
#ifdef HAVE_STRFTIME
/* fixme: we should check whether the locale apppends a " %Z"
* These locales from glibc don't put the " %Z":
* fi_FI hr_HR ja_JP lt_LT lv_LV POSIX ru_RU ru_SU sv_FI sv_SE zh_CN
*/
strftime( buffer, DIM(buffer)-1, "%c %Z", tp );
buffer[DIM(buffer)-1] = 0;
#else
mem2str( buffer, asctime(tp), DIM(buffer) );
#endif
return buffer;
}
/****************
* Print a string to FP, but filter all control characters out.
*/
void
print_string( FILE *fp, byte *p, size_t n, int delim )
{
for( ; n; n--, p++ )
if( iscntrl( *p ) || *p == delim ) {
putc('\\', fp);
if( *p == '\n' )
putc('n', fp);
else if( *p == '\r' )
putc('r', fp);
else if( *p == '\f' )
putc('f', fp);
else if( *p == '\v' )
putc('v', fp);
else if( *p == '\b' )
putc('b', fp);
else if( !*p )
putc('0', fp);
else
fprintf(fp, "x%02x", *p );
}
else
putc(*p, fp);
}
int
answer_is_yes( const char *s )
{
char *long_yes = _("yes");
char *short_yes = _("yY");
if( !stricmp(s, long_yes ) )
return 1;
if( strchr( short_yes, *s ) && !s[1] )
return 1;
return 0;
}
diff --git a/util/secmem.c b/util/secmem.c
index ffcb45674..ce93a6bf8 100644
--- a/util/secmem.c
+++ b/util/secmem.c
@@ -1,373 +1,373 @@
/* secmem.c - memory allocation from a secure heap
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <stdarg.h>
#if defined(HAVE_MLOCK) || defined(HAVE_MMAP)
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#endif
#include "types.h"
#include "memory.h"
#include "util.h"
#include "i18n.h"
#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
#define MAP_ANONYMOUS MAP_ANON
#endif
#define DEFAULT_POOLSIZE 8196
typedef struct memblock_struct MEMBLOCK;
struct memblock_struct {
unsigned size;
union {
MEMBLOCK *next;
long align_dummy;
char d[1];
} u;
};
static void *pool;
static int pool_okay;
static int pool_is_mmapped;
static size_t poolsize; /* allocated length */
static size_t poollen; /* used length */
static MEMBLOCK *unused_blocks;
static unsigned max_alloced;
static unsigned cur_alloced;
static unsigned max_blocks;
static unsigned cur_blocks;
static int disable_secmem;
static int show_warning;
static int no_warning;
static int suspend_warning;
static void
print_warn()
{
if( !no_warning )
log_info(_("Warning: using insecure memory!\n"));
}
static void
lock_pool( void *p, size_t n )
{
#ifdef HAVE_MLOCK
uid_t uid;
int err;
uid = getuid();
#ifdef HAVE_BROKEN_MLOCK
if( uid ) {
errno = EPERM;
err = errno;
}
else {
err = mlock( p, n );
if( err && errno )
err = errno;
}
#else
err = mlock( p, n );
if( err && errno )
err = errno;
#endif
if( uid && !geteuid() ) {
if( setuid( uid ) )
log_fatal("failed to reset uid: %s\n", strerror(errno));
}
if( err ) {
if( errno != EPERM
#ifdef EAGAIN /* OpenBSD returns this */
&& errno != EAGAIN
#endif
)
log_error("can´t lock memory: %s\n", strerror(err));
show_warning = 1;
}
#else
log_info("Please note that you don't have secure memory on this system\n");
#endif
}
static void
init_pool( size_t n)
{
size_t pgsize;
poolsize = n;
if( disable_secmem )
log_bug("secure memory is disabled");
#ifdef HAVE_GETPAGESIZE
pgsize = getpagesize();
#else
pgsize = 4096;
#endif
#if HAVE_MMAP
poolsize = (poolsize + pgsize -1 ) & ~(pgsize-1);
#ifdef MAP_ANONYMOUS
pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
#else /* map /dev/zero instead */
{ int fd;
fd = open("/dev/zero", O_RDWR);
if( fd == -1 ) {
log_error("can't open /dev/zero: %s\n", strerror(errno) );
pool = (void*)-1;
}
else {
pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE,
MAP_PRIVATE, fd, 0);
}
}
#endif
if( pool == (void*)-1 )
log_info("can't mmap pool of %u bytes: %s - using malloc\n",
(unsigned)poolsize, strerror(errno));
else {
pool_is_mmapped = 1;
pool_okay = 1;
}
#endif
if( !pool_okay ) {
pool = malloc( poolsize );
if( !pool )
log_fatal("can't allocate memory pool of %u bytes\n",
(unsigned)poolsize);
else
pool_okay = 1;
}
lock_pool( pool, poolsize );
poollen = 0;
}
/* concatenate unused blocks */
static void
compress_pool(void)
{
}
void
secmem_set_flags( unsigned flags )
{
int was_susp = suspend_warning;
no_warning = flags & 1;
suspend_warning = flags & 2;
/* and now issue the warning if it is not longer suspended */
if( was_susp && !suspend_warning && show_warning ) {
show_warning = 0;
print_warn();
}
}
unsigned
secmem_get_flags(void)
{
unsigned flags;
flags = no_warning ? 1:0;
flags |= suspend_warning ? 2:0;
return flags;
}
void
secmem_init( size_t n )
{
if( !n ) {
#ifndef __MINGW32__
uid_t uid;
disable_secmem=1;
uid = getuid();
if( uid != geteuid() ) {
if( setuid( uid ) )
log_fatal("failed to drop setuid\n" );
}
#endif
}
else {
if( n < DEFAULT_POOLSIZE )
n = DEFAULT_POOLSIZE;
if( !pool_okay )
init_pool(n);
else
log_error("Oops, secure memory pool already initialized\n");
}
}
void *
secmem_malloc( size_t size )
{
MEMBLOCK *mb, *mb2;
int compressed=0;
if( !pool_okay )
log_bug("secmem not initialized\n");
if( show_warning && !suspend_warning ) {
show_warning = 0;
print_warn();
}
/* blocks are always a multiple of 32 */
size += sizeof(MEMBLOCK);
size = ((size + 31) / 32) * 32;
retry:
/* try to get it from the used blocks */
for(mb = unused_blocks,mb2=NULL; mb; mb2=mb, mb = mb->u.next )
if( mb->size >= size ) {
if( mb2 )
mb2->u.next = mb->u.next;
else
unused_blocks = mb->u.next;
goto leave;
}
/* allocate a new block */
if( (poollen + size <= poolsize) ) {
mb = (void*)((char*)pool + poollen);
poollen += size;
mb->size = size;
}
else if( !compressed ) {
compressed=1;
compress_pool();
goto retry;
}
else
return NULL;
leave:
cur_alloced += mb->size;
cur_blocks++;
if( cur_alloced > max_alloced )
max_alloced = cur_alloced;
if( cur_blocks > max_blocks )
max_blocks = cur_blocks;
return &mb->u.d;
}
void *
secmem_realloc( void *p, size_t newsize )
{
MEMBLOCK *mb;
size_t size;
void *a;
mb = (MEMBLOCK*)((char*)p - ((size_t) &((MEMBLOCK*)0)->u.d));
size = mb->size;
if( newsize < size )
return p; /* it is easier not to shrink the memory */
a = secmem_malloc( newsize );
memcpy(a, p, size);
memset((char*)a+size, 0, newsize-size);
secmem_free(p);
return a;
}
void
secmem_free( void *a )
{
MEMBLOCK *mb;
size_t size;
if( !a )
return;
mb = (MEMBLOCK*)((char*)a - ((size_t) &((MEMBLOCK*)0)->u.d));
size = mb->size;
memset(mb, 0xff, size );
memset(mb, 0xaa, size );
memset(mb, 0x55, size );
memset(mb, 0x00, size );
mb->size = size;
mb->u.next = unused_blocks;
unused_blocks = mb;
cur_blocks--;
cur_alloced -= size;
}
int
m_is_secure( const void *p )
{
return p >= pool && p < (void*)((char*)pool+poolsize);
}
void
secmem_term()
{
if( !pool_okay )
return;
memset( pool, 0xff, poolsize);
memset( pool, 0xaa, poolsize);
memset( pool, 0x55, poolsize);
memset( pool, 0x00, poolsize);
#if HAVE_MMAP
if( pool_is_mmapped )
munmap( pool, poolsize );
#endif
pool = NULL;
pool_okay = 0;
poolsize=0;
poollen=0;
unused_blocks=NULL;
}
void
secmem_dump_stats()
{
if( disable_secmem )
return;
fprintf(stderr,
"secmem usage: %u/%u bytes in %u/%u blocks of pool %lu/%lu\n",
cur_alloced, max_alloced, cur_blocks, max_blocks,
(ulong)poollen, (ulong)poolsize );
}
diff --git a/util/strgutil.c b/util/strgutil.c
index 20489dabf..d5379f903 100644
--- a/util/strgutil.c
+++ b/util/strgutil.c
@@ -1,389 +1,389 @@
/* strgutil.c - miscellaneous utilities
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "types.h"
#include "util.h"
#include "memory.h"
static int use_koi8 = 0;
static ushort koi82unicode[128] = {
0x2500,0x2502,0x250c,0x2510,0x2514,0x2518,0x251c,0x2524,
0x252c,0x2534,0x253c,0x2580,0x2584,0x2588,0x258c,0x2590,
0x2591,0x2592,0x2593,0x2320,0x25a0,0x2219,0x221a,0x2248,
0x2264,0x2265,0x00a0,0x2321,0x00b0,0x00b2,0x00b7,0x00f7,
0x2550,0x2551,0x2552,0x0451,0x2553,0x2554,0x2555,0x2556,
0x2557,0x2558,0x2559,0x255a,0x255b,0x255c,0x255d,0x255e,
0x255f,0x2560,0x2561,0x0401,0x2562,0x2563,0x2564,0x2565,
0x2566,0x2567,0x2568,0x2569,0x256a,0x256b,0x256c,0x00a9,
0x044e,0x0430,0x0431,0x0446,0x0434,0x0435,0x0444,0x0433,
0x0445,0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,
0x043f,0x044f,0x0440,0x0441,0x0442,0x0443,0x0436,0x0432,
0x044c,0x044b,0x0437,0x0448,0x044d,0x0449,0x0447,0x044a,
0x042e,0x0410,0x0411,0x0426,0x0414,0x0415,0x0424,0x0413,
0x0425,0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,
0x041f,0x042f,0x0420,0x0421,0x0422,0x0423,0x0416,0x0412,
0x042c,0x042b,0x0417,0x0428,0x042d,0x0429,0x0427,0x042a
};
void
free_strlist( STRLIST sl )
{
STRLIST sl2;
for(; sl; sl = sl2 ) {
sl2 = sl->next;
m_free(sl);
}
}
STRLIST
add_to_strlist( STRLIST *list, const char *string )
{
STRLIST sl;
sl = m_alloc( sizeof *sl + strlen(string));
strcpy(sl->d, string);
sl->next = *list;
*list = sl;
return sl;
}
STRLIST
append_to_strlist( STRLIST *list, const char *string )
{
STRLIST r, sl;
sl = m_alloc( sizeof *sl + strlen(string));
strcpy(sl->d, string);
sl->next = NULL;
if( !*list )
*list = sl;
else {
for( r = *list; r->next; r = r->next )
;
r->next = sl;
}
return sl;
}
STRLIST
strlist_prev( STRLIST head, STRLIST node )
{
STRLIST n;
for(n=NULL; head && head != node; head = head->next )
n = head;
return n;
}
STRLIST
strlist_last( STRLIST node )
{
if( node )
for( ; node->next ; node = node->next )
;
return node;
}
/****************
* look for the substring SUB in buffer and return a pointer to that
* substring in BUF or NULL if not found.
* Comparison is case-insensitive.
*/
const char *
memistr( const char *buf, size_t buflen, const char *sub )
{
const byte *t, *s ;
size_t n;
for( t=buf, n=buflen, s=sub ; n ; t++, n-- )
if( toupper(*t) == toupper(*s) ) {
for( buf=t++, buflen = n--, s++;
n && toupper(*t) == toupper(*s); t++, s++, n-- )
;
if( !*s )
return buf;
t = buf; n = buflen; s = sub ;
}
return NULL ;
}
/****************
* Wie strncpy(), aber es werden maximal n-1 zeichen kopiert und ein
* '\0' angehängt. Ist n = 0, so geschieht nichts, ist Destination
* gleich NULL, so wird via m_alloc Speicher besorgt, ist dann nicht
* genügend Speicher vorhanden, so bricht die funktion ab.
*/
char *
mem2str( char *dest , const void *src , size_t n )
{
char *d;
const char *s;
if( n ) {
if( !dest )
dest = m_alloc( n ) ;
d = dest;
s = src ;
for(n--; n && *s; n-- )
*d++ = *s++;
*d = '\0' ;
}
return dest ;
}
/****************
* remove leading and trailing white spaces
*/
char *
trim_spaces( char *str )
{
char *string, *p, *mark;
string = str;
/* find first non space character */
for( p=string; *p && isspace( *(byte*)p ) ; p++ )
;
/* move characters */
for( (mark = NULL); (*string = *p); string++, p++ )
if( isspace( *(byte*)p ) ) {
if( !mark )
mark = string ;
}
else
mark = NULL ;
if( mark )
*mark = '\0' ; /* remove trailing spaces */
return str ;
}
int
string_count_chr( const char *string, int c )
{
int count;
for(count=0; *string; string++ )
if( *string == c )
count++;
return count;
}
int
set_native_charset( const char *newset )
{
if( !stricmp( newset, "iso-8859-1" ) )
use_koi8 = 0;
else if( !stricmp( newset, "koi8-r" ) )
use_koi8 = 1;
else
return G10ERR_GENERAL;
return 0;
}
/****************
* Convert string, which is in native encoding to UTF8 and return the
* new allocated UTF8 string.
*/
char *
native_to_utf8( const char *string )
{
const byte *s;
char *buffer;
byte *p;
size_t length=0;
if( use_koi8 ) {
for(s=string; *s; s++ ) {
length++;
if( *s & 0x80 )
length += 2; /* we may need 3 bytes */
}
buffer = m_alloc( length + 1 );
for(p=buffer, s=string; *s; s++ ) {
if( *s & 0x80 ) {
ushort val = koi82unicode[ *s & 0x7f ];
if( val < 0x0800 ) {
*p++ = 0xc0 | ( (val >> 6) & 0x1f );
*p++ = 0x80 | ( val & 0x3f );
}
else {
*p++ = 0xe0 | ( (val >> 12) & 0x0f );
*p++ = 0x80 | ( (val >> 6) & 0x3f );
*p++ = 0x80 | ( val & 0x3f );
}
}
else
*p++ = *s;
}
*p = 0;
}
else {
for(s=string; *s; s++ ) {
length++;
if( *s & 0x80 )
length++;
}
buffer = m_alloc( length + 1 );
for(p=buffer, s=string; *s; s++ ) {
if( *s & 0x80 ) {
*p++ = 0xc0 | ((*s >> 6) & 3);
*p++ = 0x80 | ( *s & 0x3f );
}
else
*p++ = *s;
}
*p = 0;
}
return buffer;
}
/****************
* Convert string, which is in UTF8 to native encoding. Replace
* illegal encodings by some "\xnn".
*/
char *
utf8_to_native( const char *string )
{
#if 0
const byte *s;
size_t n;
byte *buffer, *p;
/* quick check whether we actually have characters with bit 8 set */
for( s=string; *s; s++ )
if( *s & 0x80 )
break;
if( !*s ) /* that is easy */
return m_strdup(string);
/* count the extended utf-8 characters */
110x xxxx
1110 xxxx
1111 0xxx
for( n=1, s=string; *s; s++ ) {
if( !(*s & 0x80) )
n++;
else if( (*s & 0xe0) == 0xc0 )
n += 2;
else if( (*s & 0xf0) == 0xe0 )
n += 3;
else if( (*s & 0xf8) == 0xf0 )
n += 4;
else
n++; /* invalid encoding */
}
buffer = p = m_alloc( n );
for( s=string; *s; ) {
if( !(*s & 0x80) )
*p++ = *s++;
else if( (*s & 0xe0) == 0xc0 ) {
u32 val;
if( (s[1] & 0xc0) != 0x80 )
;
val = (*s << 6) | (s[1] & 0x3f);
}
else if( (*s & 0xf0) == 0xe0 )
n += 3;
else if( (*s & 0xf8) == 0xf0 )
n += 4;
else
n++; /* invalid encoding */
}
#endif
return m_strdup(string);
}
/****************
* check whether string is a valid UTF8 string.
* Returns 0 = Okay
* 1 = Too short
* 2 = invalid encoding
*/
int
check_utf8_string( const char *string )
{
/*fixme */
return 0;
}
/*********************************************
********** missing string functions *********
*********************************************/
#ifndef HAVE_STPCPY
char *
stpcpy(char *a,const char *b)
{
while( *b )
*a++ = *b++;
*a = 0;
return (char*)a;
}
#endif
#ifndef HAVE_STRLWR
char *
strlwr(char *s)
{
char *p;
for(p=s; *p; p++ )
*p = tolower(*p);
return s;
}
#endif
/****************
* mingw32/cpd has a memicmp()
*/
#ifndef HAVE_MEMICMP
int
memicmp( const char *a, const char *b, size_t n )
{
for( ; n; n--, a++, b++ )
if( *a != *b && toupper(*(const byte*)a) != toupper(*(const byte*)b) )
return *(const byte *)a - *(const byte*)b;
return 0;
}
#endif
diff --git a/util/ttyio.c b/util/ttyio.c
index 9f095d86e..cfc8f4dac 100644
--- a/util/ttyio.c
+++ b/util/ttyio.c
@@ -1,365 +1,365 @@
/* ttyio.c - tty i/O functions
* Copyright (C) 1998 Free Software Foundation, Inc.
*
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
*
- * GNUPG is free software; you can redistribute it and/or modify
+ * 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,
+ * 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 <stdarg.h>
#include <unistd.h>
#ifdef HAVE_TCGETATTR
#include <termios.h>
#endif
#ifdef __MINGW32__ /* use the odd Win32 functions */
#include <windows.h>
#ifdef HAVE_TCGETATTR
#error mingw32 and termios
#endif
#endif
#include <errno.h>
#include <ctype.h>
#include "util.h"
#include "memory.h"
#include "ttyio.h"
#define CONTROL_D ('D' - 'A' + 1)
#ifdef __MINGW32__ /* use the odd Win32 functions */
static struct {
HANDLE in, out;
} con;
#define DEF_INPMODE (ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT \
|ENABLE_PROCESSED_INPUT )
#define HID_INPMODE (ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT )
#define DEF_OUTMODE (ENABLE_WRAP_AT_EOL_OUTPUT|ENABLE_PROCESSED_OUTPUT)
#else /* yeah, we have a real OS */
static FILE *ttyfp = NULL;
#endif
static int initialized;
static int last_prompt_len;
#ifdef HAVE_TCGETATTR
static struct termios termsave;
static int restore_termios;
#endif
#ifdef HAVE_TCGETATTR
static void
cleanup(void)
{
if( restore_termios ) {
restore_termios = 0; /* do it prios in case it is interrupted again */
if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
log_error("tcsetattr() failed: %s\n", strerror(errno) );
}
}
#endif
static void
init_ttyfp()
{
if( initialized )
return;
#if defined(__MINGW32__)
{
SECURITY_ATTRIBUTES sa;
memset(&sa, 0, sizeof(sa));
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
con.out = CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
&sa, OPEN_EXISTING, 0, 0 );
if( con.out == INVALID_HANDLE_VALUE )
log_fatal("open(CONOUT$) failed: rc=%d", (int)GetLastError() );
memset(&sa, 0, sizeof(sa));
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
con.in = CreateFileA( "CONIN$", GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
&sa, OPEN_EXISTING, 0, 0 );
if( con.in == INVALID_HANDLE_VALUE )
log_fatal("open(CONIN$) failed: rc=%d", (int)GetLastError() );
}
SetConsoleMode(con.in, DEF_INPMODE );
SetConsoleMode(con.out, DEF_OUTMODE );
#else
ttyfp = fopen("/dev/tty", "r+");
if( !ttyfp )
log_fatal("cannot open /dev/tty: %s\n", strerror(errno) );
#endif
#ifdef HAVE_TCGETATTR
atexit( cleanup );
#endif
initialized = 1;
}
void
tty_printf( const char *fmt, ... )
{
va_list arg_ptr;
if( !initialized )
init_ttyfp();
va_start( arg_ptr, fmt ) ;
#ifdef __MINGW32__
{ static char *buf;
static size_t bufsize;
int n;
DWORD nwritten;
#if 0 /* the dox say, that there is a snprintf, but I didn't found
* it, so we use a static buffer for now */
do {
if( n == -1 || !buf ) {
m_free(buf);
bufsize += 200;
/* better check the new size; (we use M$ functions) */
if( bufsize > 50000 )
log_bug("vsnprintf probably failed\n");
buf = m_alloc( bufsize );
}
n = _vsnprintf(buf, bufsize-1, fmt, arg_ptr);
} while( n == -1 );
#else
if( !buf ) {
bufsize += 1000;
buf = m_alloc( bufsize );
}
n = vsprintf(buf, fmt, arg_ptr);
if( n == -1 )
log_bug("vsprintf() failed\n");
#endif
if( !WriteConsoleA( con.out, buf, n, &nwritten, NULL ) )
log_fatal("WriteConsole failed: rc=%d", (int)GetLastError() );
if( n != nwritten )
log_fatal("WriteConsole failed: %d != %ld\n", n, nwritten );
last_prompt_len += n;
}
#else
last_prompt_len += vfprintf(ttyfp,fmt,arg_ptr) ;
fflush(ttyfp);
#endif
va_end(arg_ptr);
}
/****************
* Print a string, but filter all control characters out.
*/
void
tty_print_string( byte *p, size_t n )
{
if( !initialized )
init_ttyfp();
#ifdef __MINGW32__
/* not so effective, change it if you want */
for( ; n; n--, p++ )
if( iscntrl( *p ) ) {
if( *p == '\n' )
tty_printf("\\n");
else if( !*p )
tty_printf("\\0");
else
tty_printf("\\x%02x", *p);
}
else
tty_printf("%c", *p);
#else
for( ; n; n--, p++ )
if( iscntrl( *p ) ) {
putc('\\', ttyfp);
if( *p == '\n' )
putc('n', ttyfp);
else if( !*p )
putc('0', ttyfp);
else
fprintf(ttyfp, "x%02x", *p );
}
else
putc(*p, ttyfp);
#endif
}
static char *
do_get( const char *prompt, int hidden )
{
char *buf;
byte cbuf[1];
int c, n, i;
if( !initialized )
init_ttyfp();
last_prompt_len = 0;
tty_printf( prompt );
buf = m_alloc(n=50);
i = 0;
#if __MINGW32__ /* windoze version */
if( hidden )
SetConsoleMode(con.in, HID_INPMODE );
for(;;) {
DWORD nread;
if( !ReadConsoleA( con.in, cbuf, 1, &nread, NULL ) )
log_fatal("ReadConsole failed: rc=%d", (int)GetLastError() );
if( !nread )
continue;
if( *cbuf == '\n' )
break;
if( !hidden )
last_prompt_len++;
c = *cbuf;
if( c == '\t' )
c = ' ';
else if( c > 0xa0 )
; /* we don't allow 0xa0, as this is a protected blank which may
* confuse the user */
else if( iscntrl(c) )
continue;
if( !(i < n-1) ) {
n += 50;
buf = m_realloc( buf, n );
}
buf[i++] = c;
}
if( hidden )
SetConsoleMode(con.in, DEF_INPMODE );
#else /* unix version */
if( hidden ) {
#ifdef HAVE_TCGETATTR
struct termios term;
if( tcgetattr(fileno(ttyfp), &termsave) )
log_fatal("tcgetattr() failed: %s\n", strerror(errno) );
restore_termios = 1;
term = termsave;
term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
if( tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) )
log_fatal("tcsetattr() failed: %s\n", strerror(errno) );
#endif
}
/* fixme: How can we avoid that the \n is echoed w/o disabling
* canonical mode - w/o this kill_prompt can't work */
while( read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n' ) {
if( !hidden )
last_prompt_len++;
c = *cbuf;
if( c == CONTROL_D )
log_info("control d found\n");
if( c == '\t' )
c = ' ';
else if( c > 0xa0 )
; /* we don't allow 0xa0, as this is a protected blank which may
* confuse the user */
else if( iscntrl(c) )
continue;
if( !(i < n-1) ) {
n += 50;
buf = m_realloc( buf, n );
}
buf[i++] = c;
}
if( *cbuf != '\n' ) {
buf[0] = CONTROL_D;
i = 1;
}
if( hidden ) {
#ifdef HAVE_TCGETATTR
if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
log_error("tcsetattr() failed: %s\n", strerror(errno) );
restore_termios = 0;
#endif
}
#endif /* end unix version */
buf[i] = 0;
return buf;
}
char *
tty_get( const char *prompt )
{
return do_get( prompt, 0 );
}
char *
tty_get_hidden( const char *prompt )
{
return do_get( prompt, 1 );
}
void
tty_kill_prompt()
{
if( !initialized )
init_ttyfp();
if( !last_prompt_len )
return;
#if __MINGW32__
tty_printf("\r%*s\r", last_prompt_len, "");
#else
{
int i;
putc('\r', ttyfp);
for(i=0; i < last_prompt_len; i ++ )
putc(' ', ttyfp);
putc('\r', ttyfp);
fflush(ttyfp);
}
#endif
last_prompt_len = 0;
}
int
tty_get_answer_is_yes( const char *prompt )
{
int yes;
char *p = tty_get( prompt );
tty_kill_prompt();
yes = answer_is_yes(p);
m_free(p);
return yes;
}

File Metadata

Mime Type
text/x-diff
Expires
Fri, Dec 5, 9:31 AM (23 h, 53 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
58/5a/5283acda1789449d93098d43e8f5

Event Timeline