mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
This commit was manufactured by cvs2svn to create branch
'GNUPG-1-9-BRANCH'.
This commit is contained in:
parent
8d76177f10
commit
82a17c9fb3
324
ABOUT-NLS
324
ABOUT-NLS
@ -1,324 +0,0 @@
|
||||
Notes on the Free Translation Project
|
||||
*************************************
|
||||
|
||||
Free software is going international! The Free Translation Project
|
||||
is a way to get maintainers of free software, translators, and users all
|
||||
together, so that will gradually become able to speak many languages.
|
||||
A few packages already provide translations for their messages.
|
||||
|
||||
If you found this `ABOUT-NLS' file inside a distribution, you may
|
||||
assume that the distributed package does use GNU `gettext' internally,
|
||||
itself available at your nearest GNU archive site. But you do _not_
|
||||
need to install GNU `gettext' prior to configuring, installing or using
|
||||
this package with messages translated.
|
||||
|
||||
Installers will find here some useful hints. These notes also
|
||||
explain how users should proceed for getting the programs to use the
|
||||
available translations. They tell how people wanting to contribute and
|
||||
work at translations should contact the appropriate team.
|
||||
|
||||
When reporting bugs in the `intl/' directory or bugs which may be
|
||||
related to internationalization, you should tell about the version of
|
||||
`gettext' which is used. The information can be found in the
|
||||
`intl/VERSION' file, in internationalized packages.
|
||||
|
||||
Quick configuration advice
|
||||
==========================
|
||||
|
||||
If you want to exploit the full power of internationalization, you
|
||||
should configure it using
|
||||
|
||||
./configure --with-included-gettext
|
||||
|
||||
to force usage of internationalizing routines provided within this
|
||||
package, despite the existence of internationalizing capabilities in the
|
||||
operating system where this package is being installed. So far, only
|
||||
the `gettext' implementation in the GNU C library version 2 provides as
|
||||
many features (such as locale alias, message inheritance, automatic
|
||||
charset conversion or plural form handling) as the implementation here.
|
||||
It is also not possible to offer this additional functionality on top
|
||||
of a `catgets' implementation. Future versions of GNU `gettext' will
|
||||
very likely convey even more functionality. So it might be a good idea
|
||||
to change to GNU `gettext' as soon as possible.
|
||||
|
||||
So you need _not_ provide this option if you are using GNU libc 2 or
|
||||
you have installed a recent copy of the GNU gettext package with the
|
||||
included `libintl'.
|
||||
|
||||
INSTALL Matters
|
||||
===============
|
||||
|
||||
Some packages are "localizable" when properly installed; the
|
||||
programs they contain can be made to speak your own native language.
|
||||
Most such packages use GNU `gettext'. Other packages have their own
|
||||
ways to internationalization, predating GNU `gettext'.
|
||||
|
||||
By default, this package will be installed to allow translation of
|
||||
messages. It will automatically detect whether the system already
|
||||
provides the GNU `gettext' functions. If not, the GNU `gettext' own
|
||||
library will be used. This library is wholly contained within this
|
||||
package, usually in the `intl/' subdirectory, so prior installation of
|
||||
the GNU `gettext' package is _not_ required. Installers may use
|
||||
special options at configuration time for changing the default
|
||||
behaviour. The commands:
|
||||
|
||||
./configure --with-included-gettext
|
||||
./configure --disable-nls
|
||||
|
||||
will respectively bypass any pre-existing `gettext' to use the
|
||||
internationalizing routines provided within this package, or else,
|
||||
_totally_ disable translation of messages.
|
||||
|
||||
When you already have GNU `gettext' installed on your system and run
|
||||
configure without an option for your new package, `configure' will
|
||||
probably detect the previously built and installed `libintl.a' file and
|
||||
will decide to use this. This might be not what is desirable. You
|
||||
should use the more recent version of the GNU `gettext' library. I.e.
|
||||
if the file `intl/VERSION' shows that the library which comes with this
|
||||
package is more recent, you should use
|
||||
|
||||
./configure --with-included-gettext
|
||||
|
||||
to prevent auto-detection.
|
||||
|
||||
The configuration process will not test for the `catgets' function
|
||||
and therefore it will not be used. The reason is that even an
|
||||
emulation of `gettext' on top of `catgets' could not provide all the
|
||||
extensions of the GNU `gettext' library.
|
||||
|
||||
Internationalized packages have usually many `po/LL.po' files, where
|
||||
LL gives an ISO 639 two-letter code identifying the language. Unless
|
||||
translations have been forbidden at `configure' time by using the
|
||||
`--disable-nls' switch, all available translations are installed
|
||||
together with the package. However, the environment variable `LINGUAS'
|
||||
may be set, prior to configuration, to limit the installed set.
|
||||
`LINGUAS' should then contain a space separated list of two-letter
|
||||
codes, stating which languages are allowed.
|
||||
|
||||
Using This Package
|
||||
==================
|
||||
|
||||
As a user, if your language has been installed for this package, you
|
||||
only have to set the `LANG' environment variable to the appropriate
|
||||
`LL_CC' combination. Here `LL' is an ISO 639 two-letter language code,
|
||||
and `CC' is an ISO 3166 two-letter country code. For example, let's
|
||||
suppose that you speak German and live in Germany. At the shell
|
||||
prompt, merely execute `setenv LANG de_DE' (in `csh'),
|
||||
`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash').
|
||||
This can be done from your `.login' or `.profile' file, once and for
|
||||
all.
|
||||
|
||||
You might think that the country code specification is redundant.
|
||||
But in fact, some languages have dialects in different countries. For
|
||||
example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The
|
||||
country code serves to distinguish the dialects.
|
||||
|
||||
Not all programs have translations for all languages. By default, an
|
||||
English message is shown in place of a nonexistent translation. If you
|
||||
understand other languages, you can set up a priority list of languages.
|
||||
This is done through a different environment variable, called
|
||||
`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG'
|
||||
for the purpose of message handling, but you still need to have `LANG'
|
||||
set to the primary language; this is required by other parts of the
|
||||
system libraries. For example, some Swedish users who would rather
|
||||
read translations in German than English for when Swedish is not
|
||||
available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'.
|
||||
|
||||
In the `LANGUAGE' environment variable, but not in the `LANG'
|
||||
environment variable, `LL_CC' combinations can be abbreviated as `LL'
|
||||
to denote the language's main dialect. For example, `de' is equivalent
|
||||
to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT'
|
||||
(Portuguese as spoken in Portugal) in this context.
|
||||
|
||||
Translating Teams
|
||||
=================
|
||||
|
||||
For the Free Translation Project to be a success, we need interested
|
||||
people who like their own language and write it well, and who are also
|
||||
able to synergize with other translators speaking the same language.
|
||||
Each translation team has its own mailing list. The up-to-date list of
|
||||
teams can be found at the Free Translation Project's homepage,
|
||||
`http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams"
|
||||
area.
|
||||
|
||||
If you'd like to volunteer to _work_ at translating messages, you
|
||||
should become a member of the translating team for your own language.
|
||||
The subscribing address is _not_ the same as the list itself, it has
|
||||
`-request' appended. For example, speakers of Swedish can send a
|
||||
message to `sv-request@li.org', having this message body:
|
||||
|
||||
subscribe
|
||||
|
||||
Keep in mind that team members are expected to participate
|
||||
_actively_ in translations, or at solving translational difficulties,
|
||||
rather than merely lurking around. If your team does not exist yet and
|
||||
you want to start one, or if you are unsure about what to do or how to
|
||||
get started, please write to `translation@iro.umontreal.ca' to reach the
|
||||
coordinator for all translator teams.
|
||||
|
||||
The English team is special. It works at improving and uniformizing
|
||||
the terminology in use. Proven linguistic skill are praised more than
|
||||
programming skill, here.
|
||||
|
||||
Available Packages
|
||||
==================
|
||||
|
||||
Languages are not equally supported in all packages. The following
|
||||
matrix shows the current state of internationalization, as of September
|
||||
2001. The matrix shows, in regard of each package, for which languages
|
||||
PO files have been submitted to translation coordination, with a
|
||||
translation percentage of at least 50%.
|
||||
|
||||
Ready PO files bg cs da de el en eo es et fi fr gl he hr id it ja
|
||||
+----------------------------------------------------+
|
||||
a2ps | [] [] [] |
|
||||
bash | [] [] [] [] |
|
||||
bfd | |
|
||||
binutils | [] |
|
||||
bison | [] [] [] [] [] |
|
||||
clisp | [] [] [] [] |
|
||||
cpio | [] [] [] [] [] |
|
||||
diffutils | [] [] [] [] [] [] [] |
|
||||
enscript | [] [] |
|
||||
error | [] [] |
|
||||
fetchmail | |
|
||||
fileutils | [] [] [] [] [] [] [] [] |
|
||||
findutils | [] [] [] [] [] [] [] [] |
|
||||
flex | [] [] [] |
|
||||
freetype | |
|
||||
gas | |
|
||||
gawk | [] [] |
|
||||
gcal | |
|
||||
gcc | |
|
||||
gettext | [] [] [] [] [] [] [] [] [] [] |
|
||||
gnupg | [] [] [] [] [] [] [] |
|
||||
gprof | |
|
||||
grep | [] [] [] [] [] [] [] [] |
|
||||
hello | [] [] [] [] [] [] [] [] [] [] [] |
|
||||
id-utils | [] [] [] |
|
||||
indent | [] [] [] [] [] |
|
||||
jpilot | [] |
|
||||
kbd | |
|
||||
ld | [] |
|
||||
libc | [] [] [] [] [] [] [] [] |
|
||||
lilypond | [] |
|
||||
lynx | [] [] [] [] |
|
||||
m4 | [] [] [] [] [] [] [] [] |
|
||||
make | [] [] [] [] [] [] |
|
||||
mysecretdiary | [] |
|
||||
nano | [] [] [] |
|
||||
opcodes | |
|
||||
parted | [] [] [] |
|
||||
ptx | [] [] [] [] [] [] [] |
|
||||
python | |
|
||||
recode | [] [] [] [] [] [] [] [] [] |
|
||||
sed | [] [] [] [] [] [] [] [] [] [] [] [] |
|
||||
sh-utils | [] [] [] [] [] [] [] [] [] [] |
|
||||
sharutils | [] [] [] [] [] [] [] [] |
|
||||
sketch | |
|
||||
soundtracker | [] [] [] |
|
||||
sp | |
|
||||
tar | [] [] [] [] [] [] [] [] |
|
||||
texinfo | [] [] [] [] [] [] |
|
||||
textutils | [] [] [] [] [] [] [] [] |
|
||||
util-linux | [] [] |
|
||||
wdiff | [] [] [] |
|
||||
wget | [] [] [] [] [] [] [] [] [] [] |
|
||||
+----------------------------------------------------+
|
||||
bg cs da de el en eo es et fi fr gl he hr id it ja
|
||||
0 14 24 32 11 1 8 23 13 1 33 22 4 0 7 9 18
|
||||
|
||||
ko lv nb nl nn no pl pt pt_BR ru sk sl sv tr uk zh
|
||||
+----------------------------------------------------+
|
||||
a2ps | [] [] [] | 6
|
||||
bash | | 4
|
||||
bfd | | 0
|
||||
binutils | | 1
|
||||
bison | [] | 6
|
||||
clisp | [] | 5
|
||||
cpio | [] [] [] [] [] | 10
|
||||
diffutils | [] [] [] [] | 11
|
||||
enscript | [] [] [] | 5
|
||||
error | [] [] | 4
|
||||
fetchmail | | 0
|
||||
fileutils | [] [] [] [] [] [] [] [] [] | 17
|
||||
findutils | [] [] [] [] [] [] [] [] | 16
|
||||
flex | [] [] [] | 6
|
||||
freetype | | 0
|
||||
gas | | 0
|
||||
gawk | [] | 3
|
||||
gcal | | 0
|
||||
gcc | | 0
|
||||
gettext | [] [] [] [] [] [] [] [] | 18
|
||||
gnupg | [] [] [] | 10
|
||||
gprof | | 0
|
||||
grep | [] [] [] [] | 12
|
||||
hello | [] [] [] [] [] [] [] [] [] [] [] | 22
|
||||
id-utils | [] [] [] | 6
|
||||
indent | [] [] [] [] [] [] [] | 12
|
||||
jpilot | | 1
|
||||
kbd | [] | 1
|
||||
ld | | 1
|
||||
libc | [] [] [] [] [] [] [] [] | 16
|
||||
lilypond | [] [] | 3
|
||||
lynx | [] [] [] [] | 8
|
||||
m4 | [] [] [] [] | 12
|
||||
make | [] [] [] [] [] [] | 12
|
||||
mysecretdiary | | 1
|
||||
nano | [] | 4
|
||||
opcodes | [] | 1
|
||||
parted | [] [] | 5
|
||||
ptx | [] [] [] [] [] [] [] [] | 15
|
||||
python | | 0
|
||||
recode | [] [] [] [] | 13
|
||||
sed | [] [] [] [] [] [] [] | 19
|
||||
sh-utils | [] [] [] [] [] [] [] [] [] [] [] | 21
|
||||
sharutils | [] [] [] | 11
|
||||
sketch | | 0
|
||||
soundtracker | | 3
|
||||
sp | | 0
|
||||
tar | [] [] [] [] [] [] [] | 15
|
||||
texinfo | [] | 7
|
||||
textutils | [] [] [] [] [] [] [] [] | 16
|
||||
util-linux | [] [] | 4
|
||||
wdiff | [] [] [] [] | 7
|
||||
wget | [] [] [] [] [] [] [] | 17
|
||||
+----------------------------------------------------+
|
||||
33 teams ko lv nb nl nn no pl pt pt_BR ru sk sl sv tr uk zh
|
||||
53 domains 9 1 6 20 0 6 17 1 13 25 10 11 23 21 2 2 387
|
||||
|
||||
Some counters in the preceding matrix are higher than the number of
|
||||
visible blocks let us expect. This is because a few extra PO files are
|
||||
used for implementing regional variants of languages, or language
|
||||
dialects.
|
||||
|
||||
For a PO file in the matrix above to be effective, the package to
|
||||
which it applies should also have been internationalized and
|
||||
distributed as such by its maintainer. There might be an observable
|
||||
lag between the mere existence a PO file and its wide availability in a
|
||||
distribution.
|
||||
|
||||
If September 2001 seems to be old, you may fetch a more recent copy
|
||||
of this `ABOUT-NLS' file on most GNU archive sites. The most
|
||||
up-to-date matrix with full percentage details can be found at
|
||||
`http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'.
|
||||
|
||||
Using `gettext' in new packages
|
||||
===============================
|
||||
|
||||
If you are writing a freely available program and want to
|
||||
internationalize it you are welcome to use GNU `gettext' in your
|
||||
package. Of course you have to respect the GNU Library General Public
|
||||
License which covers the use of the GNU `gettext' library. This means
|
||||
in particular that even non-free programs can use `libintl' as a shared
|
||||
library, whereas only free software can use `libintl' as a static
|
||||
library or use modified versions of `libintl'.
|
||||
|
||||
Once the sources are changed appropriately and the setup can handle
|
||||
to use of `gettext' the only thing missing are the translations. The
|
||||
Free Translation Project is also available for packages which are not
|
||||
developed inside the GNU project. Therefore the information given above
|
||||
applies also for every other Free Software Project. Contact
|
||||
`translation@iro.umontreal.ca' to make the `.pot' files available to
|
||||
the translation teams.
|
||||
|
12
BUGS
12
BUGS
@ -1,12 +0,0 @@
|
||||
Please see
|
||||
|
||||
http://www.gnupg.org/buglist.html
|
||||
|
||||
for a list of know bugs in GnuPG. We don't distribute this list anymore
|
||||
with the package because a more current one with notes in which version
|
||||
the bug is fixed can be found online.
|
||||
|
||||
For security related bugs, please contact <security@gnupg.org> which
|
||||
directs mails only to the core developers. If you need to encrypt the
|
||||
report you should use the public keys of the maintainer and of 2 or 3
|
||||
other active developers (consult the ChangeLog and AUTHORS).
|
231
INSTALL
231
INSTALL
@ -1,231 +0,0 @@
|
||||
Copyright 1994, 1995, 1996, 1999, 2000, 2001 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
||||
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, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. (Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.)
|
||||
|
||||
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 you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You only need
|
||||
`configure.ac' 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. Run `./configure --help'
|
||||
for details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for variables by setting
|
||||
them in the environment. You can do that on the command line like this:
|
||||
|
||||
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
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 support 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' cannot 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 cannot guess the host type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
|
||||
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 should
|
||||
use the `--target=TYPE' option to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the host
|
||||
platform (i.e., that on which the generated programs will eventually be
|
||||
run) with `--host=TYPE'. In this case, you should also specify the
|
||||
build platform with `--build=TYPE', because, in this case, it may not
|
||||
be possible to guess the build platform (it sometimes involves
|
||||
compiling and running simple test programs, and this can't be done if
|
||||
the compiler is a cross compiler).
|
||||
|
||||
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.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
will cause the specified gcc to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--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.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
46
NOTES
46
NOTES
@ -1,46 +0,0 @@
|
||||
Checking ElGamal signatures is really slow and the reason for the long
|
||||
running time on parts o my keyring. Because somekeys are also checked at startup, this is even worser. I should invalidate my self signature with algo 16 or 20.
|
||||
|
||||
|
||||
SCO UnixWare/7.1.0 reported by Allan Clark <allanc@sco.com> for 0.9.8
|
||||
|
||||
|
||||
Some other reported cpu-vendor-os strings:
|
||||
|
||||
hppa1.1-hp-hpux10.20
|
||||
mips-sgi-irix6.2
|
||||
sparc-sun-solaris5.4
|
||||
sparc-sun-sunos4.1.2
|
||||
i386-pc-sysv4.2 (USL Unixware v1.1.2)
|
||||
powerpc-ibm-aix4.3.2.0 John Payne <jcapayne@att.com>
|
||||
|
||||
gpg 1.0.1 okay with MP-RAS 3.02.01 Edition 5 using gcc 2.95.2 and EGD
|
||||
By <CSpeicher@eisi.com>
|
||||
|
||||
gpg 1.0.1 okay with 4.0.1 BSDI BSD/OS 4.0 i386
|
||||
|
||||
|
||||
rndw32 tested on:
|
||||
|
||||
Windows 98 4.10.1998 mit einem AMD-K6-2-450
|
||||
Michael Engels <angel@dalrin.de>)
|
||||
|
||||
Windows 95 4.00.950a
|
||||
|
||||
Windows NT 4.00.1381
|
||||
|
||||
|
||||
|
||||
|
||||
tried to compile GnuPG on AIX 4.3 on a power CPU based machine. It
|
||||
doesn't work out of the box but i found a way to do so:
|
||||
|
||||
PowerPC based machines:
|
||||
CFLAGS="-g -O2 -mcpu=powerpc" ./configure --disable-asm --disable-dynload
|
||||
+--enable-static-rnd=egd
|
||||
|
||||
Power1 and Power2 machines:
|
||||
CFLAGS="-g -O2 -mcpu=power" ./configure --disable-asm --disable-dynload
|
||||
+--enable-static-rnd=egd
|
||||
|
||||
|
102
OBUGS
102
OBUGS
@ -1,102 +0,0 @@
|
||||
List of fixed bugs
|
||||
--------------------
|
||||
|
||||
(format: severity: [ *] to [***], no, first reported, by, version)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[ *] #1
|
||||
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. The reason for this problem is that pgp2 sometimes
|
||||
converts CR,LF to CR,CR,LF and to fix for this it hashes both
|
||||
versions. I was able to reproduce such a problem, that PGP263in
|
||||
was not able to verify it's own signature.
|
||||
FIX: 1999-05-19 (Most cases are now handled)
|
||||
|
||||
[***] #2 1999-02-21
|
||||
Problem while importing or deleting public keys in 0.9.3 - 0.9.2
|
||||
worked fine. Error message:
|
||||
gpg:[stdin]: key A6A59DB9: secret key not found: public key not found
|
||||
FIX: 1999-02-22 wk
|
||||
|
||||
[ *] #5
|
||||
/home/jam/.gnupg/pubring.gpg: can't open gdbm file: Can't be writer
|
||||
keyblock resource `/home/jam/.gnupg/pubring.gpg': file open error
|
||||
OOPS in close enum_keyblocks - ignored
|
||||
[gdbm is experimental and will be replaced by the new keybox code]
|
||||
FIX: 1999-07-22 (Fixed the second error, there will be no fix for
|
||||
the first one, because GDBM is to be replaced)
|
||||
|
||||
[ *] #7 1999-02-22 <dwpalmer@dwpalm.jf.intel.com> 0.9.3
|
||||
Conventional encryption incompatibility:
|
||||
$ gpg -c --cipher-algo cast5 --compress-algo 1 --no-comment secrets.txt
|
||||
Creates a file that gpg can decrypt, but PGP 5.5 has problems with it.
|
||||
PGP decrypts 6416k out of 6424k, then complains with "PGP Warning",
|
||||
"The keyring contains a bad (corrupted) PGP packet". The resulting
|
||||
file is missing information from the front.
|
||||
FIX: 1999-02-26 temporary fix in encrypt_simple()
|
||||
|
||||
|
||||
[ *] #8 1999-02-25 <kazu@iijlab.net> 0.9.3
|
||||
%gpg --encrypt -r kazu@iijlab.net --batch foo
|
||||
gpg: Warning: using insecure memory!
|
||||
gpg: 11C23F61: no info to calculate a trust probability
|
||||
This creates a symmetrically encrypted message WITHOUT a session key
|
||||
encrypted with public cryptographic(i.e. foo.gpg). This is probably
|
||||
FIX: 199-02-26 wk
|
||||
|
||||
[ **] #9 1999-02-25
|
||||
Misalignment in md5.c#md5_write.
|
||||
FIX: 1999-02-26 wk
|
||||
|
||||
[ **] #10 1999-03-01
|
||||
Armor detection code is broken. Direct import of keyrings is not possible.
|
||||
FIX: 1999-03-02 wk
|
||||
|
||||
[***] #11 1999-02-25
|
||||
"cipher algo 10 not found".
|
||||
FIX: 1999-02-25 wk
|
||||
|
||||
[ **] #12 1999-03-10
|
||||
gpg --list-secret-keys --with-colon SEGVs
|
||||
FIX: 1999-03-10
|
||||
|
||||
[ *] #13 1999-04-05
|
||||
Trying to generate very large keys fails with a BUG in read_pool()
|
||||
FIX: 1999-04-06
|
||||
|
||||
|
||||
[ *] #14 1999-04-05 <anonymous>
|
||||
If you use --s2k-cipher-algo twofish, the the program crashes with
|
||||
a BUG at line 226 of passphrase.c.
|
||||
FIX: 1999-04-06
|
||||
|
||||
|
||||
[ **] #15 1999-04-05
|
||||
Hash calculation for subkey bindings is not according to rfc2440 if
|
||||
a 4 byte length header is used for the subkey.
|
||||
FIX: 1999-04-06
|
||||
|
||||
[***] #16 1999-03-23 <jafo@tummy.com>
|
||||
Verifying detached signatures with an empty file yields a rc of 0.
|
||||
FIX: 1999-05-06
|
||||
|
||||
[ **] #17 1999-05-18 <Bodo_Moeller@public.uni-hamburg.de> 0.9.6
|
||||
Import does not detect identical user IDs.
|
||||
FIX: 1999-05-22
|
||||
|
||||
[ **] #19 1999-06-11
|
||||
"trustdb transaction too large" with about 500 signatures on a key
|
||||
FAEBD5FC.
|
||||
FIX: 1999-07-12 (less memory requirement and increased the limit)
|
||||
|
||||
[ **] #20 1999-06-16 <jashley@yorktown.designlab.ukans.edu> 0.9.7
|
||||
Using "addkey" in the edit menu with more than 1 subkey leads to
|
||||
"out of secure memory" in some cases.
|
||||
FIX: 1999-06-17 (Twofish uses too much memory and the memory
|
||||
becomes fragmented - workaround is using CAST5 to protect passphrases)
|
||||
|
||||
[ *] #21 1999-06-17
|
||||
Ctrl-D does not work correct for messages entered at the tty.
|
||||
FIX: 1999-06-18 (Better EOF detection on terminals)
|
||||
|
46
PROJECTS
46
PROJECTS
@ -1,46 +0,0 @@
|
||||
|
||||
* Change the internal representation 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.
|
||||
|
||||
* Add a way to override the current cipher/md implementations
|
||||
by others (using extensions)
|
||||
|
||||
* Not GnuPG related: What about option completion in bash?
|
||||
Can "--dump-options" be used for this or should we place the
|
||||
options in an ELF note section?
|
||||
|
||||
* Split key support (n-out-of-m). Use our own protocol or figure out
|
||||
how PGP does it.
|
||||
|
||||
* 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?)
|
||||
Hmmm, we better drop the duplication of the public part and just keep
|
||||
the secrets in the "secring" - this has the additional that we can
|
||||
put those secrets on a hardware token.
|
||||
|
||||
* write a tool to extract selected keys from a file.
|
||||
|
||||
* Change the buffering to a mbuf like scheme? See Michael's proposal.
|
||||
|
||||
* Keep a list of duplicate, faked or unwanted keyids.
|
||||
|
||||
* The current code has knowledge about the structure of a keyblock.
|
||||
We should add an abstraction layer so that adding support for
|
||||
different certificate structures will become easier.
|
||||
|
||||
* "Michael T. Babcock" <mbabcock@fibrespeed.net> suggested to write
|
||||
an event log so that other software can display a key history or
|
||||
alike with GnuPG results. This should be connected to the keyrings.
|
||||
|
||||
|
||||
|
||||
Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is free software; as a special exception the author gives
|
||||
unlimited permission to copy and/or distribute it, with or without
|
||||
modifications, as long as this notice is preserved.
|
||||
|
||||
This file is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
275
THOUGHTS
275
THOUGHTS
@ -1,275 +0,0 @@
|
||||
How often have we to do a key lookup by mailaddress?.
|
||||
can this be accomplished by an external program?
|
||||
|
||||
|
||||
|
||||
What about using S-Exp to describe the interface to the ciphers instead
|
||||
of simply iterating over them. This way we can easy register a name which
|
||||
can be used as the "hintstr" for --load-extension.
|
||||
|
||||
EGD
|
||||
====
|
||||
Oh, and on embedding egd into the gpg package: I think if you just unpack it
|
||||
into, say, util/egd/* then you can put something like this into configure.in:
|
||||
|
||||
AC_CHECK_PROG(perl_present, perl, true, false)
|
||||
if $perl_present; then
|
||||
AC_PATH_PROG(PERL, perl)
|
||||
(cd util/egd; $PERL Makefile.PL FULLPERL=$PERL INSTALLBIN=$sbindir)
|
||||
fi
|
||||
AM_CONDITIONAL(WITH_EGD, $perl_present)
|
||||
|
||||
and add util/egd to the top-level Makefile directory list inside a WITH_EGD
|
||||
conditional.
|
||||
|
||||
* What shall we do if we have a valid subkey revocation certificate
|
||||
but no subkey binding? Is this a valid but revoked key?
|
||||
|
||||
* use a mmaped file for secure memory if mlock does not work and
|
||||
make sure that this file is always wiped out. Is this really
|
||||
more secure than swapping out to the swap disk? I don't
|
||||
believe so because if an attacker has access to the physical
|
||||
box (and he needs this to look at the swap area) he can also
|
||||
leave a Trojan horse which is far more easier than to analyze
|
||||
memory dumps. Question: Is it possible that a Unix pages
|
||||
an old (left over by some other process) swap page in for
|
||||
another process - this should be considered a serious design
|
||||
flow/bug.
|
||||
|
||||
Date: Mon, 4 Jan 1999 19:34:29 -0800 (PST)
|
||||
From: Matthew Skala <mskala@ansuz.sooke.bc.ca>
|
||||
|
||||
- Signing with an expired key doesn't work by default, does work with a
|
||||
special option.
|
||||
- Verifying a signature that appears to have been made by an expired key
|
||||
after its expiry date but is otherwise good reports the signature as BAD,
|
||||
preferably with a message indicating that it's a key-expiry problem rather
|
||||
than a cryptographically bad signature.
|
||||
- Verifying a signature from a key that is now expired, where the
|
||||
signature was made before the expiry date, reports the signature as
|
||||
GOOD, possibly with a warning that the key has since expired.
|
||||
- Encrypting to an expired key doesn't work by default, does work with a
|
||||
special option.
|
||||
- Decrypting always works, if you have the appropriate secret key and
|
||||
passphrase.
|
||||
|
||||
|
||||
|
||||
==============================
|
||||
[ "-->" indicates a comment by me (wk) ]
|
||||
|
||||
Hi Werner..
|
||||
|
||||
I was looking at some of the PROJECTS items in the recent gpg CVS and wanted
|
||||
to comment on one of them:
|
||||
|
||||
* Add a way to override the current cipher/md implementations
|
||||
by others (using extensions)
|
||||
|
||||
As you know I've been thinking about how to use a PalmPilot or an iButton in
|
||||
some useful way in GPG. The two things that seem reasonable are:
|
||||
1) keep the secret key in the device, only transferring it to the host
|
||||
computer for the duration of the secret-key operation (sign or decrypt).
|
||||
The key is never kept on disk, only in RAM. This removes the chance that
|
||||
casual snooping on your office workstation will reveal your key (it
|
||||
doesn't help against an active attack, but the attacker must leave a
|
||||
tampered version of GPG around or otherwise get their code to run while
|
||||
the key-storage device is attached to attack the key)
|
||||
2) perform the secret-key operation on the device, so the secret key never
|
||||
leaves the confines of that device. There are still attacks possible,
|
||||
based upon talking to the device while it is connected and trying to
|
||||
convince the device (and possibly the user) that it is the real GPG,
|
||||
but in general this protects the key pretty strongly. Any individual
|
||||
message is still vulnerable, but that's a tradeoff of the convenience of
|
||||
composing that message on a full-sized screen+keyboard (plus the added
|
||||
speed of encryption) vs. the security of writing the message on a
|
||||
secure device.
|
||||
|
||||
I think there are a variety of ways of implementing these things, but a few
|
||||
extension mechanisms in GPG should be enough to try various ways later on.
|
||||
|
||||
1) pass an argument string to loadable extension modules (maybe
|
||||
gpg --load-extension foofish=arg1,arg2,arg3 ?)
|
||||
--> could also be achived by S-Exps
|
||||
|
||||
2) allow multiple instances of the same extension module (presumably with
|
||||
different arguments)
|
||||
--> set an alias name when loading them
|
||||
3) allow extension modules to use stdin/stdout/stderr as normal (probably
|
||||
already in there), for giving feedback to the user, or possibly asking them
|
||||
for a password of some sort
|
||||
--> there should really be some kind of callback mechanism.
|
||||
|
||||
4) have an extension to provide secret keys:
|
||||
|
||||
It looks like most of the hooks for this are already in place, it just
|
||||
needs an extension module which can register itself as a keyblock resource.
|
||||
|
||||
I'm thinking of a module for this that is given an external program name as
|
||||
an argument. When the keyblock resource is asked to enumerate its keys, it
|
||||
runs the external program (first with a "0" argument, then a "1", and so on
|
||||
until the program reports that no more keys are available). The external
|
||||
--> better use a cookie: This way we are also stateless but have a more
|
||||
general interface.
|
||||
|
||||
program returns one (possibly armored) secret key block each time. The
|
||||
program might have some kind of special protocol to talk to the storage
|
||||
device. One thing that comes to mind is to simply include a random number
|
||||
in the message sent over the serial port: the program would display this
|
||||
number, the Pilot at the other end would display the number it receives, if
|
||||
the user sees that both are the same they instruct the Pilot to release the
|
||||
key, as basic protection against someone else asking for the key while it
|
||||
is attached. More sophisticated schemes are possible depending upon how
|
||||
much processing power and IO is available on the device. But the same
|
||||
extension module should be able to handle as complex a scheme as one could
|
||||
wish.
|
||||
--> authenticate the session on startup, using DH and the mentioned
|
||||
cookie/screen/keyboard authentication.
|
||||
|
||||
The current keyblock-resource interface would work fine, although it
|
||||
might be more convenient if a resource could be asked for a key by id
|
||||
instead of enumerating all of them and then searching through the resulting
|
||||
list for a match. A module that provided public keys would have to work this
|
||||
way (imagine a module that could automatically do an http fetch for a
|
||||
particular key.. easily-added automatic key fetching). Without that ability
|
||||
to fetch by id (which would require it to fall back to the other keyblock
|
||||
resources if it failed), the user's device might be asked to release the
|
||||
key even though some other secret key was the one needed.
|
||||
--> Right.
|
||||
|
||||
|
||||
5) have an extension to perform a secret-key operation without the actual
|
||||
secret key material
|
||||
--> Define a clear interface to do this and in the first step write
|
||||
a daemon which does exactly this.
|
||||
|
||||
basically something to indicate that any decrypt or sign operations that
|
||||
occur for a specific keyid should call the extension module instead. The
|
||||
secret key would not be extracted (it wouldn't be available anyway). The
|
||||
module is given the keyid and the MPI of the block it is supposed to sign
|
||||
or decrypt.
|
||||
|
||||
The module could then run an external program to do the operation. I'm
|
||||
imagining a Pilot program which receives the data, asks the user if it can go
|
||||
along with the operation (after displaying a hash of the request, which is
|
||||
also displayed by the extension module's program to make sure the Pilot is
|
||||
being asked to do the right operation), performs the signature or decryption,
|
||||
then returns the data. This protocol could be made arbitrarily complex, with
|
||||
a D-H key to encrypt the link, and both sides signing requests to
|
||||
authenticate one to the other (although this transforms the the problem of
|
||||
getting your secret key off your office workstation into the problem of
|
||||
your workstation holding a key tells your Pilot that it is allowed to perform
|
||||
the secret key operation, and if someone gets a hold of that key they may
|
||||
be able to trick your pilot [plugged in somewhere else] to do the same thing
|
||||
for them).
|
||||
|
||||
This is basically red/black separation, with the Pilot or iButton having the
|
||||
perimeter beyond which the red data doesn't pass. Better than the secret-key
|
||||
storage device but requires a lot more power on the device (the new iButtons
|
||||
with the exponentiator could do it, but it would take way too much code space
|
||||
on the old ones, although they would be fine for just carrying the keys).
|
||||
|
||||
The signature code might need to be extended to verify the signature you just
|
||||
made, since an active intruder pretending to the the Pilot wouldn't be able to
|
||||
make a valid signature (but they might sign your message with a different key
|
||||
just to be annoying).
|
||||
|
||||
Anyway, just wanted to share my thoughts on some possibilities. I've been
|
||||
carrying this little Java iButton on my keyring for months now, looking for
|
||||
something cool to do with it, and I think that secure storage for my GPG key
|
||||
would be just the right application.
|
||||
|
||||
cheers,
|
||||
-Brian
|
||||
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v0.4.5 (GNU/Linux)
|
||||
Comment: For info finger gcrypt@ftp.guug.de
|
||||
|
||||
iD8DBQE2c5oZkDmgv9E5zEwRArAwAKDWV5fpTtbGPiMPgl2Bpp0gvhbfQgCgzJuY
|
||||
AmIQTk4s62/y2zMAHDdOzK0=
|
||||
=jr7m
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
|
||||
|
||||
About a new Keyserver (discussion with Allan Clark <allanc@sco.com>):
|
||||
=====================
|
||||
|
||||
Some ideas:
|
||||
|
||||
o the KS should verify signatures and only accept those
|
||||
which are good.
|
||||
|
||||
o Keep a blacklist of known bad signatures to minimize
|
||||
the time needed to check them
|
||||
|
||||
o Should be fast - I'm currently designing a new storage
|
||||
system called keybox which takes advantage of the fact
|
||||
that the keyID is highly random and can directly be
|
||||
used as a hash value and this keyID is (for v4 keys)
|
||||
part of the fingerprint: So it is possible to use the
|
||||
fingerprint as key but do an lookup by the keyID.
|
||||
|
||||
o To be used as the "public keyring" in a LAN so that there
|
||||
is no need to keep one on every machine.
|
||||
|
||||
o Allow more that one file for key storage.
|
||||
|
||||
o Use the HKS protocol and enhance it in a way that binary
|
||||
keyrings can be transmitted. (I already wrote some
|
||||
http server and client code which can be used for this)
|
||||
And extend it to allow reuse of a connection.
|
||||
|
||||
o Keep a checksum (hash) of the entire keyblock so that a
|
||||
client can easy check whether this keyblock has changed.
|
||||
(keyblock = the entire key with all certificates etc.)
|
||||
Transmitted in the HEAD info.
|
||||
|
||||
o Allow efficient propagation of new keys and revocation
|
||||
certificates.
|
||||
|
||||
|
||||
Probably more things but this keyserver is not a goal for the
|
||||
1.0 release. Someone should be able to fix some of the limitations
|
||||
of the existing key servers (I think they bail out on some rfc2440
|
||||
packet formats).
|
||||
|
||||
|
||||
DJGPP
|
||||
=====
|
||||
Don't use symlinks but try to do the preprocessing in the config-links script.
|
||||
DJPGG has problems to distinguish betwen .s and .S becaus the FAT filesystem
|
||||
is not case sensitive (Mark Elbrecht).
|
||||
Well, it runs only on one architecture and therefor it might be possible
|
||||
to add a special case for it, completely bypassing the symlink autselection
|
||||
trick.
|
||||
|
||||
Special procmail addresses
|
||||
==========================
|
||||
* foo+bar@example.net: Try to match the address without the "+bar".
|
||||
Should be done by the MUA, but maybe we can do this.
|
||||
--> Yep. Another reason to utilize a directory service or something
|
||||
else for keylookup.
|
||||
|
||||
|
||||
|
||||
Suggested things which I will not do:
|
||||
=====================================
|
||||
* Let take --help an option to select some topics.
|
||||
Using grep is much easier
|
||||
* 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.
|
||||
--> Use a script and --status-fd
|
||||
|
||||
|
||||
Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is free software; as a special exception the author gives
|
||||
unlimited permission to copy and/or distribute it, with or without
|
||||
modifications, as long as this notice is preserved.
|
||||
|
||||
This file is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
419
agent/ChangeLog
419
agent/ChangeLog
@ -1,419 +0,0 @@
|
||||
2002-09-25 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg-agent.c (handle_signal): Flush cache on SIGHUP.
|
||||
* cache.c (agent_flush_cache): New.
|
||||
|
||||
* gpg-agent.c, agent.h: Add --keep-display and --keep-tty.
|
||||
* query.c (start_pinentry): Implement them. The option passing
|
||||
needs more thoughts.
|
||||
|
||||
2002-09-09 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg-agent.c (create_private_keys_directory)
|
||||
(create_directories): New.
|
||||
(main): Try to create a home directory.
|
||||
|
||||
2002-09-04 Neal H. Walfield <neal@g10code.de>
|
||||
|
||||
* gpg-agent.c (main): Use sigaction, not signal.
|
||||
|
||||
2002-09-03 Neal H. Walfield <neal@g10code.de>
|
||||
|
||||
* findkey.c: Include <fcntl.h>.
|
||||
(agent_write_private_key): Prefer POSIX compatibity, open and
|
||||
fdopen, over the simplicity of GNU extensions, fopen(file, "x").
|
||||
|
||||
2002-08-22 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* query.c (agent_askpin): Provide the default desc text depending
|
||||
on the pininfo. Do the basic PIN verification only when
|
||||
min_digits is set.
|
||||
|
||||
2002-08-21 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* query.c (agent_askpin): Hack to show the right default prompt.
|
||||
(agent_get_passphrase): Ditto.
|
||||
|
||||
* trans.c: Removed and replaced all usages with standard _()
|
||||
|
||||
* divert-scd.c (getpin_cb): Pass a more descritive text to the
|
||||
pinentry.
|
||||
|
||||
* Makefile.am: Renamed the binary protect-tool to gpg-protect-tool.
|
||||
* protect-tool.c: Removed the note about internal use only.
|
||||
|
||||
* gpg-agent.c (main): New option --daemon so that the program is
|
||||
not accidently started in the background.
|
||||
|
||||
2002-08-16 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* call-scd.c (learn_status_cb): Handle CERTINFO status.
|
||||
(agent_card_learn): Add args for certinfo cb.
|
||||
* learncard.c (release_certinfo,certinfo_cb): New.
|
||||
(send_cert_back): New. With factored out code from ..
|
||||
(agent_handle_learn): here. Return certinfo stuff.
|
||||
|
||||
2002-07-26 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg-agent.c (main): New option --ignore-cache-for-signing.
|
||||
* command.c (option_handler): New server option
|
||||
use-cache-for-signing defaulting to true.
|
||||
(cmd_pksign): handle global and per session option.
|
||||
* findkey.c (agent_key_from_file, unprotect): New arg
|
||||
ignore_cache. Changed all callers.
|
||||
* pksign.c (agent_pksign): Likewise.
|
||||
|
||||
2002-06-29 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* query.c (start_pinentry): Use GNUPG_DERAULT_PINENTRY.
|
||||
* call-scd.c (start_scd): Use GNUPG_DEFAULT_SCDAEMON.
|
||||
|
||||
2002-06-28 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* protect-tool.c (export_p12_file): New.
|
||||
(main): New command --p12-export.
|
||||
* minip12.c (create_final,p12_build,compute_tag_length): New.
|
||||
(store_tag_length): New.
|
||||
|
||||
2002-06-27 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* minip12.c (crypt_block): Renamed from decrypt_block, add arg to
|
||||
allow encryption.
|
||||
|
||||
* Makefile.am (pkglib_PROGRAMS): Put protect-tool there.
|
||||
|
||||
* findkey.c (agent_write_private_key,agent_key_from_file)
|
||||
(agent_key_available): Use GNUPG_PRIVATE_KEYS_DIR constant.
|
||||
* gpg-agent.c (main): Use GNUPG_DEFAULT_HOMEDIR constant.
|
||||
|
||||
* protect-tool.c (store_private_key): New.
|
||||
(import_p12_file): Store the new file if requested.
|
||||
(main): New options --force and --store.
|
||||
|
||||
* gpg-agent.c (main): Set a global flag when running detached.
|
||||
* query.c (start_pinentry): Pass the list of FD to keep in the
|
||||
child when not running detached.
|
||||
* call-scd.c (start_scd): Ditto.
|
||||
|
||||
2002-06-26 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* command.c (cmd_istrusted, cmd_listtrusted, cmd_marktrusted)
|
||||
(cmd_pksign, cmd_pkdecrypt, cmd_genkey, cmd_get_passphrase)
|
||||
(cmd_learn): Print an error message for a failed operation.
|
||||
|
||||
* simple-pwquery.c, simple-pwquery.h: New.
|
||||
* protect-tool. (get_passphrase): New, used to get a passphrase
|
||||
from the agent if none was given on the command line.
|
||||
|
||||
2002-06-25 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* protect-tool.c (rsa_key_check): New.
|
||||
(import_p12_file): New.
|
||||
(main): New command --p12-import.
|
||||
* minip12.c, minip12.h: New.
|
||||
|
||||
2002-06-24 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* protect-tool.c (read_file): New.
|
||||
(read_key): Factored most code out to read_file.
|
||||
|
||||
2002-06-17 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* agent.h: Add a callback function to the pin_entry_info structure.
|
||||
* query.c (agent_askpin): Use the callback to check for a correct
|
||||
PIN. Removed the start_err_text argument because it is not
|
||||
anymore needed; changed callers.
|
||||
* findkey.c (unprotect): Replace our own check loop by a callback.
|
||||
(try_unprotect_cb): New.
|
||||
* genkey.c (reenter_compare_cb): New.
|
||||
(agent_genkey): Use this callback here. Fixed setting of the pi2
|
||||
variable and a segv in case of an empty PIN.
|
||||
|
||||
* divert-scd.c (getpin_cb): Removed some unused stuff and
|
||||
explained what we still have to change.
|
||||
|
||||
2002-06-12 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg-agent.c (main): New option --disable-pth.
|
||||
|
||||
2002-06-11 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* protect-tool.c: Add command --show-keygrip
|
||||
(show_keygrip): New.
|
||||
|
||||
2002-05-23 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* call-scd.c: Seirialized all scdaeom access when using Pth.
|
||||
|
||||
* cache.c: Made the cache Pth-thread-safe.
|
||||
(agent_unlock_cache_entry): New.
|
||||
* findkey.c (unprotect): Unlock the returned cache value.
|
||||
* command.c (cmd_get_passphrase): Ditto.
|
||||
|
||||
* gpg-agent.c (main): Register pth_read/write with Assuan.
|
||||
|
||||
2002-05-22 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* query.c: Serialized all pinentry access when using Pth.
|
||||
|
||||
* gpg-agent.c (handle_signal,start_connection_thread)
|
||||
(handle_connections): New
|
||||
(main): Use the new Pth stuff to allow concurrent connections.
|
||||
* command.c (start_command_handler): Add new arg FD so that the
|
||||
fucntion can also be used for an already connected socket.
|
||||
* Makefile.am: Link with Pth.
|
||||
|
||||
2002-05-14 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* cache.c (housekeeping, agent_put_cache): Use our time() wrapper.
|
||||
|
||||
2002-04-26 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* cache.c (agent_put_cache): Reinitialize the creation time and
|
||||
the ttl when reusing a slot.
|
||||
|
||||
* call-scd.c (start_scd): Print debug messages only with debug
|
||||
flags set.
|
||||
* query.c (start_pinentry): Ditto.
|
||||
|
||||
2002-04-25 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* agent.h (agent_get_confirmation): Replace paramter prompt with
|
||||
two parameters ok and cancel.
|
||||
* query.c (agent_get_confirmation): Likewise. Implement this.
|
||||
* trustlist.c (agent_marktrusted): Fix invocation of
|
||||
agent_get_confirmation.
|
||||
* divert-scd.c (ask_for_card): Likewise.
|
||||
|
||||
2002-04-24 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* agent.h (struct opt): Add members display, ttyname, ttytype,
|
||||
lc_ctype, and lc_messages.
|
||||
* gpg-agent.c (enum cmd_and_opt_values): Add oDisplay, oTTYname,
|
||||
oTTYtype, oLCctype, and LCmessages.
|
||||
(main): Handle these options.
|
||||
* command.c (option_handler): New function.
|
||||
(register_commands): Register option handler.
|
||||
* query.c (start_pinentry): Pass the various display and tty
|
||||
options to the pinentry.
|
||||
|
||||
2002-04-05 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* protect-tool.c (show_file): New. Used as default action.
|
||||
|
||||
2002-03-28 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* divert-scd.c (encode_md_for_card): Don't do the pkcs-1 padding,
|
||||
the scdaemon should take care of it.
|
||||
(ask_for_card): Hack to not display the trailing zero.
|
||||
|
||||
2002-03-11 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* learncard.c (kpinfo_cb): Remove the content restrictions from
|
||||
the keyID.
|
||||
|
||||
2002-03-06 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* learncard.c: New.
|
||||
* divert-scd.c (ask_for_card): The serial number is binary so
|
||||
convert it to hex here.
|
||||
* findkey.c (agent_write_private_key): New.
|
||||
* genkey.c (store_key): And use it here.
|
||||
|
||||
* pkdecrypt.c (agent_pkdecrypt): Changed the way the diversion is done.
|
||||
* divert-scd.c (divert_pkdecrypt): Changed interface and
|
||||
implemented it.
|
||||
|
||||
2002-03-05 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* call-scd.c (inq_needpin): New.
|
||||
(agent_card_pksign): Add getpin_cb args.
|
||||
(agent_card_pkdecrypt): New.
|
||||
|
||||
2002-03-04 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* pksign.c (agent_pksign): Changed how the diversion is done.
|
||||
* divert-scd.c (divert_pksign): Changed interface and implemented it.
|
||||
(encode_md_for_card): New.
|
||||
* call-scd.c (agent_card_pksign): New.
|
||||
|
||||
2002-02-28 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* pksign.c (agent_pksign): Detect whether a Smartcard is to be
|
||||
used and divert the operation in this case.
|
||||
* pkdecrypt.c (agent_pkdecrypt): Likewise
|
||||
* findkey.c (agent_key_from_file): Add optional arg shadow_info
|
||||
and have it return information about a shadowed key.
|
||||
* protect.c (agent_get_shadow_info): New.
|
||||
|
||||
* protect.c (snext,sskip,smatch): Moved to
|
||||
* sexp-parse.h: new file.
|
||||
* divert-scd.c: New.
|
||||
|
||||
2002-02-27 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* protect.c (agent_shadow_key): New.
|
||||
|
||||
* command.c (cmd_learn): New command LEARN.
|
||||
* gpg-agent.c: New option --scdaemon-program.
|
||||
* call-scd.c (start_scd): New. Based on query.c
|
||||
* query.c: Add 2 more arguments to all uses of assuan_transact.
|
||||
|
||||
2002-02-18 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* findkey.c (unprotect): Show an error message for a bad passphrase.
|
||||
|
||||
* command.c (cmd_marktrusted): Implemented.
|
||||
* trustlist.c (agent_marktrusted): New.
|
||||
(open_list): Add APPEND arg.
|
||||
|
||||
* query.c (agent_get_confirmation): New.
|
||||
|
||||
2002-02-06 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* cache.c (housekeeping): Fixed linking in the remove case.
|
||||
|
||||
2002-02-01 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg-agent.c: New option --default-cache-ttl.
|
||||
* cache.c (agent_put_cache): Use it.
|
||||
|
||||
* cache.c: Add a few debug outputs.
|
||||
|
||||
* protect.c (agent_private_key_type): New.
|
||||
* agent.h: Add PRIVATE_KEY_ enums.
|
||||
* findkey.c (agent_key_from_file): Use it to decide whether we
|
||||
have to unprotect a key.
|
||||
(unprotect): Cache the passphrase.
|
||||
|
||||
* findkey.c (agent_key_from_file,agent_key_available): The key
|
||||
files do now require a ".key" suffix to make a script's life
|
||||
easier.
|
||||
* genkey.c (store_key): Ditto.
|
||||
|
||||
2002-01-31 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* genkey.c (store_key): Protect the key.
|
||||
(agent_genkey): Ask for the passphrase.
|
||||
* findkey.c (unprotect): Actually unprotect the key.
|
||||
* query.c (agent_askpin): Add an optional start_err_text.
|
||||
|
||||
2002-01-30 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* protect.c: New.
|
||||
(hash_passphrase): Based on the GnuPG 1.0.6 version.
|
||||
* protect-tool.c: New
|
||||
|
||||
2002-01-29 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* findkey.c (agent_key_available): New.
|
||||
* command.c (cmd_havekey): New.
|
||||
(register_commands): And register new command.
|
||||
|
||||
2002-01-20 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* command.c (cmd_get_passphrase): Remove the plus signs.
|
||||
|
||||
* query.c (start_pinentry): Send no-grab option to pinentry
|
||||
* gpg-agent.c (main): Move variable grab as no_grab to agent.h.
|
||||
|
||||
2002-01-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg-agent.c (main): Disable core dumps.
|
||||
|
||||
* cache.c: New.
|
||||
* command.c (cmd_get_passphrase): Use the cache.
|
||||
(cmd_clear_passphrase): Ditto.
|
||||
|
||||
* gpg-agent.c: Removed unused cruft and implement the socket
|
||||
based server.
|
||||
(my_strusage): Take bug report address from configure.ac.
|
||||
* command.c (start_command_handler): Add an argument to start as
|
||||
regular server.
|
||||
(start_command_handler): Enable Assuan logging.
|
||||
|
||||
2002-01-15 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* trustlist.c: New.
|
||||
* command.c (cmd_istrusted, cmd_listtrusted, cmd_marktrusted): New.
|
||||
|
||||
2002-01-07 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* genkey.c: Store the secret part and return the public part.
|
||||
|
||||
2002-01-03 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* command.c (cmd_get_passphrase): New.
|
||||
(cmd_clear_passphrase): New.
|
||||
* query.c (agent_get_passphrase): New.
|
||||
|
||||
2002-01-02 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* genkey.c: New.
|
||||
* command.c (cmd_genkey): New.
|
||||
|
||||
* command.c (rc_to_assuan_status): Removed and changed all callers
|
||||
to use map_to_assuan_status.
|
||||
|
||||
2001-12-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* keyformat.txt: New.
|
||||
|
||||
2001-12-19 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* query.c (start_pinentry): Add new argument to assuan_pipe_connect.
|
||||
|
||||
2001-12-18 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* Makefile.am: Use LIBGCRYPT macros
|
||||
|
||||
2001-12-14 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg-agent.c (main): New option --batch. New option --debug-wait
|
||||
n, so that it is possible to attach gdb when used in server mode.
|
||||
* query.c (agent_askpin): Don't ask in batch mode.
|
||||
|
||||
* command.c: Removed the conversion macros as they are now in
|
||||
../common/util.h.
|
||||
|
||||
2001-12-14 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* query.c (LINELENGTH): Removed.
|
||||
(agent_askpin): Use ASSUAN_LINELENGTH, not LINELENGTH.
|
||||
|
||||
2001-11-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg-agent.c: Removed all GUI code, removed code for old
|
||||
protocol. New code to use the Assuan protocol as a server and
|
||||
also to communicate with a new ask-passphrase utility.
|
||||
|
||||
2000-11-22 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* gpg-agent.c (main): csh support by Dan Winship, new options --sh
|
||||
and --csh and set default by consulting $SHELL.
|
||||
|
||||
Mon Aug 21 17:59:17 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* gpg-agent.c (passphrase_dialog): Cleanup the window and added the
|
||||
user supplied text to the window.
|
||||
(main): Fixed segv in gtk_init when used without a command to start.
|
||||
|
||||
* gpg-agent.c: --flush option.
|
||||
(req_flush): New.
|
||||
(req_clear_passphrase): Implemented.
|
||||
|
||||
Fri Aug 18 14:27:14 CEST 2000 Werner Koch <wk@openit.de>
|
||||
|
||||
* gpg-agent.c: New.
|
||||
* Makefile.am: New.
|
||||
|
||||
|
||||
Copyright 2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is free software; as a special exception the author gives
|
||||
unlimited permission to copy and/or distribute it, with or without
|
||||
modifications, as long as this notice is preserved.
|
||||
|
||||
This file is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
@ -1,62 +0,0 @@
|
||||
# Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GnuPG.
|
||||
#
|
||||
# GnuPG is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# GnuPG is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
localedir = $(datadir)/locale
|
||||
INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\"
|
||||
|
||||
bin_PROGRAMS = gpg-agent
|
||||
pkglib_PROGRAMS = gpg-protect-tool
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/common $(LIBGCRYPT_CFLAGS) $(PTH_CFLAGS)
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
gpg_agent_SOURCES = \
|
||||
gpg-agent.c agent.h \
|
||||
command.c \
|
||||
query.c \
|
||||
cache.c \
|
||||
trans.c \
|
||||
findkey.c \
|
||||
pksign.c \
|
||||
pkdecrypt.c \
|
||||
genkey.c \
|
||||
protect.c \
|
||||
trustlist.c \
|
||||
divert-scd.c \
|
||||
call-scd.c \
|
||||
learncard.c \
|
||||
sexp-parse.h
|
||||
|
||||
|
||||
gpg_agent_LDADD = ../jnlib/libjnlib.a ../assuan/libassuan.a \
|
||||
../common/libcommon.a $(LIBGCRYPT_LIBS) $(PTH_LIBS)
|
||||
|
||||
gpg_protect_tool_SOURCES = \
|
||||
protect-tool.c \
|
||||
protect.c \
|
||||
minip12.c minip12.h \
|
||||
simple-pwquery.c simple-pwquery.h
|
||||
|
||||
gpg_protect_tool_LDADD = ../jnlib/libjnlib.a \
|
||||
../common/libcommon.a $(LIBGCRYPT_LIBS)
|
||||
|
||||
|
||||
|
||||
|
197
agent/agent.h
197
agent/agent.h
@ -1,197 +0,0 @@
|
||||
/* agent.h - Global definitions for the agent
|
||||
* Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#ifndef AGENT_H
|
||||
#define AGENT_H
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "../common/util.h"
|
||||
#include "../common/errors.h"
|
||||
|
||||
#define MAX_DIGEST_LEN 24
|
||||
|
||||
/* A large struct name "opt" to keep global flags */
|
||||
struct {
|
||||
unsigned int debug; /* debug flags (DBG_foo_VALUE) */
|
||||
int verbose; /* verbosity level */
|
||||
int quiet; /* be as quiet as possible */
|
||||
int dry_run; /* don't change any persistent data */
|
||||
int batch; /* batch mode */
|
||||
const char *homedir; /* configuration directory name */
|
||||
const char *pinentry_program;
|
||||
char *display;
|
||||
char *ttyname;
|
||||
char *ttytype;
|
||||
char *lc_ctype;
|
||||
char *lc_messages;
|
||||
const char *scdaemon_program;
|
||||
int no_grab; /* don't let the pinentry grab the keyboard */
|
||||
unsigned long def_cache_ttl;
|
||||
|
||||
int running_detached; /* we are running detached from the tty. */
|
||||
|
||||
int ignore_cache_for_signing;
|
||||
int keep_tty; /* don't switch the TTY (for pinentry) on request */
|
||||
int keep_display; /* don't switch the DISPLAY (for pinentry) on request */
|
||||
} opt;
|
||||
|
||||
|
||||
#define DBG_COMMAND_VALUE 1 /* debug commands i/o */
|
||||
#define DBG_MPI_VALUE 2 /* debug mpi details */
|
||||
#define DBG_CRYPTO_VALUE 4 /* debug low level crypto */
|
||||
#define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */
|
||||
#define DBG_CACHE_VALUE 64 /* debug the caching */
|
||||
#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */
|
||||
#define DBG_HASHING_VALUE 512 /* debug hashing operations */
|
||||
#define DBG_ASSUAN_VALUE 1024
|
||||
|
||||
#define DBG_COMMAND (opt.debug & DBG_COMMAND_VALUE)
|
||||
#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE)
|
||||
#define DBG_MEMORY (opt.debug & DBG_MEMORY_VALUE)
|
||||
#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
|
||||
#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
|
||||
#define DBG_ASSUAN (opt.debug & DBG_ASSUAN_VALUE)
|
||||
|
||||
struct server_local_s;
|
||||
|
||||
struct server_control_s {
|
||||
struct server_local_s *server_local;
|
||||
struct {
|
||||
int algo;
|
||||
unsigned char value[MAX_DIGEST_LEN];
|
||||
int valuelen;
|
||||
} digest;
|
||||
char keygrip[20];
|
||||
int have_keygrip;
|
||||
|
||||
};
|
||||
typedef struct server_control_s *CTRL;
|
||||
|
||||
|
||||
struct pin_entry_info_s {
|
||||
int min_digits; /* min. number of digits required or 0 for freeform entry */
|
||||
int max_digits; /* max. number of allowed digits allowed*/
|
||||
int max_tries;
|
||||
int failed_tries;
|
||||
int (*check_cb)(struct pin_entry_info_s *); /* CB used to check the PIN */
|
||||
void *check_cb_arg; /* optional argument which might be of use in the CB */
|
||||
const char *cb_errtext; /* used by the cb to displaye a specific error */
|
||||
size_t max_length; /* allocated length of the buffer */
|
||||
char pin[1];
|
||||
};
|
||||
|
||||
|
||||
enum {
|
||||
PRIVATE_KEY_UNKNOWN = 0,
|
||||
PRIVATE_KEY_CLEAR = 1,
|
||||
PRIVATE_KEY_PROTECTED = 2,
|
||||
PRIVATE_KEY_SHADOWED = 3
|
||||
};
|
||||
|
||||
/*-- gpg-agent.c --*/
|
||||
void agent_exit (int rc); /* also implemented in other tools */
|
||||
|
||||
/*-- command.c --*/
|
||||
void start_command_handler (int, int);
|
||||
|
||||
/*-- findkey.c --*/
|
||||
int agent_write_private_key (const unsigned char *grip,
|
||||
const void *buffer, size_t length, int force);
|
||||
GCRY_SEXP agent_key_from_file (const unsigned char *grip,
|
||||
unsigned char **shadow_info, int ignore_cache);
|
||||
int agent_key_available (const unsigned char *grip);
|
||||
|
||||
/*-- query.c --*/
|
||||
int agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo);
|
||||
int agent_get_passphrase (char **retpass,
|
||||
const char *desc, const char *prompt,
|
||||
const char *errtext);
|
||||
int agent_get_confirmation (const char *desc, const char *ok,
|
||||
const char *cancel);
|
||||
|
||||
/*-- cache.c --*/
|
||||
void agent_flush_cache (void);
|
||||
int agent_put_cache (const char *key, const char *data, int ttl);
|
||||
const char *agent_get_cache (const char *key, void **cache_id);
|
||||
void agent_unlock_cache_entry (void **cache_id);
|
||||
|
||||
|
||||
/*-- pksign.c --*/
|
||||
int agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache);
|
||||
|
||||
/*-- pkdecrypt.c --*/
|
||||
int agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen,
|
||||
FILE *outfp);
|
||||
|
||||
/*-- genkey.c --*/
|
||||
int agent_genkey (CTRL ctrl,
|
||||
const char *keyparam, size_t keyparmlen, FILE *outfp);
|
||||
|
||||
/*-- protect.c --*/
|
||||
int agent_protect (const unsigned char *plainkey, const char *passphrase,
|
||||
unsigned char **result, size_t *resultlen);
|
||||
int agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
|
||||
unsigned char **result, size_t *resultlen);
|
||||
int agent_private_key_type (const unsigned char *privatekey);
|
||||
int agent_shadow_key (const unsigned char *pubkey,
|
||||
const unsigned char *shadow_info,
|
||||
unsigned char **result);
|
||||
int agent_get_shadow_info (const unsigned char *shadowkey,
|
||||
unsigned char const **shadow_info);
|
||||
|
||||
|
||||
/*-- trustlist.c --*/
|
||||
int agent_istrusted (const char *fpr);
|
||||
int agent_listtrusted (void *assuan_context);
|
||||
int agent_marktrusted (const char *name, const char *fpr, int flag);
|
||||
|
||||
|
||||
/*-- divert-scd.c --*/
|
||||
int divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
|
||||
const unsigned char *shadow_info, unsigned char **r_sig);
|
||||
int divert_pkdecrypt (const unsigned char *cipher,
|
||||
const unsigned char *shadow_info,
|
||||
char **r_buf, size_t *r_len);
|
||||
|
||||
/*-- call-scd.c --*/
|
||||
int agent_card_learn (void (*kpinfo_cb)(void*, const char *),
|
||||
void *kpinfo_cb_arg,
|
||||
void (*certinfo_cb)(void*, const char *),
|
||||
void *certinfo_cb_arg);
|
||||
int agent_card_serialno (char **r_serialno);
|
||||
int agent_card_pksign (const char *keyid,
|
||||
int (*getpin_cb)(void *, const char *, char*, size_t),
|
||||
void *getpin_cb_arg,
|
||||
const unsigned char *indata, size_t indatalen,
|
||||
char **r_buf, size_t *r_buflen);
|
||||
int agent_card_pkdecrypt (const char *keyid,
|
||||
int (*getpin_cb)(void *, const char *, char*,size_t),
|
||||
void *getpin_cb_arg,
|
||||
const unsigned char *indata, size_t indatalen,
|
||||
char **r_buf, size_t *r_buflen);
|
||||
int agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen);
|
||||
int agent_card_readkey (const char *id, unsigned char **r_buf);
|
||||
|
||||
|
||||
/*-- learncard.c --*/
|
||||
int agent_handle_learn (void *assuan_context);
|
||||
|
||||
|
||||
#endif /*AGENT_H*/
|
314
agent/cache.c
314
agent/cache.c
@ -1,314 +0,0 @@
|
||||
/* cache.c - keep a cache of passphrases
|
||||
* Copyright (C) 2002 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 <time.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "agent.h"
|
||||
|
||||
struct secret_data_s {
|
||||
int totallen; /* this includes the padding */
|
||||
int datalen; /* actual data length */
|
||||
char data[1];
|
||||
};
|
||||
|
||||
typedef struct cache_item_s *ITEM;
|
||||
struct cache_item_s {
|
||||
ITEM next;
|
||||
time_t created;
|
||||
time_t accessed;
|
||||
int ttl; /* max. lifetime given in seonds */
|
||||
int lockcount;
|
||||
struct secret_data_s *pw;
|
||||
char key[1];
|
||||
};
|
||||
|
||||
|
||||
static ITEM thecache;
|
||||
|
||||
|
||||
static void
|
||||
release_data (struct secret_data_s *data)
|
||||
{
|
||||
xfree (data);
|
||||
}
|
||||
|
||||
static struct secret_data_s *
|
||||
new_data (const void *data, size_t length)
|
||||
{
|
||||
struct secret_data_s *d;
|
||||
int total;
|
||||
|
||||
/* we pad the data to 32 bytes so that it get more complicated
|
||||
finding something out by watching allocation patterns. This is
|
||||
usally not possible but we better assume nothing about our
|
||||
secure storage provider*/
|
||||
total = length + 32 - (length % 32);
|
||||
|
||||
d = gcry_malloc_secure (sizeof d + total - 1);
|
||||
if (d)
|
||||
{
|
||||
d->totallen = total;
|
||||
d->datalen = length;
|
||||
memcpy (d->data, data, length);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
/* check whether there are items to expire */
|
||||
static void
|
||||
housekeeping (void)
|
||||
{
|
||||
ITEM r, rprev;
|
||||
time_t current = gnupg_get_time ();
|
||||
|
||||
/* first expire the actual data */
|
||||
for (r=thecache; r; r = r->next)
|
||||
{
|
||||
if (!r->lockcount && r->pw && r->accessed + r->ttl < current)
|
||||
{
|
||||
if (DBG_CACHE)
|
||||
log_debug (" expired `%s' (%ds after last access)\n",
|
||||
r->key, r->ttl);
|
||||
release_data (r->pw);
|
||||
r->pw = NULL;
|
||||
r->accessed = current;
|
||||
}
|
||||
}
|
||||
|
||||
/* second, make sure that we also remove them based on the created stamp so
|
||||
that the user has to enter it from time to time. We do this every hour */
|
||||
for (r=thecache; r; r = r->next)
|
||||
{
|
||||
if (!r->lockcount && r->pw && r->created + 60*60 < current)
|
||||
{
|
||||
if (DBG_CACHE)
|
||||
log_debug (" expired `%s' (1h after creation)\n", r->key);
|
||||
release_data (r->pw);
|
||||
r->pw = NULL;
|
||||
r->accessed = current;
|
||||
}
|
||||
}
|
||||
|
||||
/* third, make sure that we don't have too many items in the list.
|
||||
Expire old and unused entries after 30 minutes */
|
||||
for (rprev=NULL, r=thecache; r; )
|
||||
{
|
||||
if (!r->pw && r->accessed + 60*30 < current)
|
||||
{
|
||||
if (r->lockcount)
|
||||
{
|
||||
log_error ("can't remove unused cache entry `%s' due to"
|
||||
" lockcount=%d\n",
|
||||
r->key, r->lockcount);
|
||||
r->accessed += 60*10; /* next error message in 10 minutes */
|
||||
rprev = r;
|
||||
r = r->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
ITEM r2 = r->next;
|
||||
if (DBG_CACHE)
|
||||
log_debug (" removed `%s' (slot not used for 30m)\n", r->key);
|
||||
xfree (r);
|
||||
if (!rprev)
|
||||
thecache = r2;
|
||||
else
|
||||
rprev->next = r2;
|
||||
r = r2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rprev = r;
|
||||
r = r->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
agent_flush_cache (void)
|
||||
{
|
||||
ITEM r;
|
||||
|
||||
if (DBG_CACHE)
|
||||
log_debug ("agent_flush_cache\n");
|
||||
|
||||
for (r=thecache; r; r = r->next)
|
||||
{
|
||||
if (!r->lockcount && r->pw)
|
||||
{
|
||||
if (DBG_CACHE)
|
||||
log_debug (" flushing `%s'\n", r->key);
|
||||
release_data (r->pw);
|
||||
r->pw = NULL;
|
||||
r->accessed = 0;
|
||||
}
|
||||
else if (r->lockcount && r->pw)
|
||||
{
|
||||
if (DBG_CACHE)
|
||||
log_debug (" marked `%s' for flushing\n", r->key);
|
||||
r->accessed = 0;
|
||||
r->ttl = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Store DATA of length DATALEN in the cache under KEY and mark it
|
||||
with a maximum lifetime of TTL seconds. If there is already data
|
||||
under this key, it will be replaced. Using a DATA of NULL deletes
|
||||
the entry */
|
||||
int
|
||||
agent_put_cache (const char *key, const char *data, int ttl)
|
||||
{
|
||||
ITEM r;
|
||||
|
||||
if (DBG_CACHE)
|
||||
log_debug ("agent_put_cache `%s'\n", key);
|
||||
housekeeping ();
|
||||
|
||||
if (ttl < 1)
|
||||
ttl = opt.def_cache_ttl;
|
||||
if (!ttl)
|
||||
return 0;
|
||||
|
||||
for (r=thecache; r; r = r->next)
|
||||
{
|
||||
if (!r->lockcount && !strcmp (r->key, key))
|
||||
break;
|
||||
}
|
||||
if (r)
|
||||
{ /* replace */
|
||||
if (r->pw)
|
||||
{
|
||||
release_data (r->pw);
|
||||
r->pw = NULL;
|
||||
}
|
||||
if (data)
|
||||
{
|
||||
r->created = r->accessed = gnupg_get_time ();
|
||||
r->ttl = ttl;
|
||||
r->pw = new_data (data, strlen (data)+1);
|
||||
if (!r->pw)
|
||||
log_error ("out of core while allocating new cache item\n");
|
||||
}
|
||||
}
|
||||
else if (data)
|
||||
{ /* simply insert */
|
||||
r = xtrycalloc (1, sizeof *r + strlen (key));
|
||||
if (!r)
|
||||
log_error ("out of core while allocating new cache control\n");
|
||||
else
|
||||
{
|
||||
strcpy (r->key, key);
|
||||
r->created = r->accessed = gnupg_get_time ();
|
||||
r->ttl = ttl;
|
||||
r->pw = new_data (data, strlen (data)+1);
|
||||
if (!r->pw)
|
||||
{
|
||||
log_error ("out of core while allocating new cache item\n");
|
||||
xfree (r);
|
||||
}
|
||||
else
|
||||
{
|
||||
r->next = thecache;
|
||||
thecache = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Try to find an item in the cache */
|
||||
const char *
|
||||
agent_get_cache (const char *key, void **cache_id)
|
||||
{
|
||||
ITEM r;
|
||||
|
||||
if (DBG_CACHE)
|
||||
log_debug ("agent_get_cache `%s'...\n", key);
|
||||
housekeeping ();
|
||||
|
||||
/* first try to find one with no locks - this is an updated cache
|
||||
entry: We might have entries with a lockcount and without a
|
||||
lockcount. */
|
||||
for (r=thecache; r; r = r->next)
|
||||
{
|
||||
if (!r->lockcount && r->pw && !strcmp (r->key, key))
|
||||
{
|
||||
/* put_cache does only put strings into the cache, so we
|
||||
don't need the lengths */
|
||||
r->accessed = gnupg_get_time ();
|
||||
if (DBG_CACHE)
|
||||
log_debug ("... hit\n");
|
||||
r->lockcount++;
|
||||
*cache_id = r;
|
||||
return r->pw->data;
|
||||
}
|
||||
}
|
||||
/* again, but this time get even one with a lockcount set */
|
||||
for (r=thecache; r; r = r->next)
|
||||
{
|
||||
if (r->pw && !strcmp (r->key, key))
|
||||
{
|
||||
r->accessed = gnupg_get_time ();
|
||||
if (DBG_CACHE)
|
||||
log_debug ("... hit (locked)\n");
|
||||
r->lockcount++;
|
||||
*cache_id = r;
|
||||
return r->pw->data;
|
||||
}
|
||||
}
|
||||
if (DBG_CACHE)
|
||||
log_debug ("... miss\n");
|
||||
|
||||
*cache_id = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
agent_unlock_cache_entry (void **cache_id)
|
||||
{
|
||||
ITEM r;
|
||||
|
||||
for (r=thecache; r; r = r->next)
|
||||
{
|
||||
if (r == *cache_id)
|
||||
{
|
||||
if (!r->lockcount)
|
||||
log_error ("trying to unlock non-locked cache entry `%s'\n",
|
||||
r->key);
|
||||
else
|
||||
r->lockcount--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
592
agent/call-scd.c
592
agent/call-scd.c
@ -1,592 +0,0 @@
|
||||
/* call-scd.c - fork of the scdaemon to do SC operations
|
||||
* Copyright (C) 2001, 2002 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
|
||||
*/
|
||||
|
||||
/* Fixme: For now we have serialized all access to the scdaemon which
|
||||
make sense becuase the scdaemon can't handle concurrent connections
|
||||
right now. We should however keep a list of connections and lock
|
||||
just that connection - it migth make sense to implemtn parts of
|
||||
this in Assuan.*/
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef USE_GNU_PTH
|
||||
# include <pth.h>
|
||||
#endif
|
||||
|
||||
#include "agent.h"
|
||||
#include "../assuan/assuan.h"
|
||||
|
||||
#ifdef _POSIX_OPEN_MAX
|
||||
#define MAX_OPEN_FDS _POSIX_OPEN_MAX
|
||||
#else
|
||||
#define MAX_OPEN_FDS 20
|
||||
#endif
|
||||
|
||||
static ASSUAN_CONTEXT scd_ctx = NULL;
|
||||
#ifdef USE_GNU_PTH
|
||||
static pth_mutex_t scd_lock = PTH_MUTEX_INIT;
|
||||
#endif
|
||||
|
||||
/* callback parameter for learn card */
|
||||
struct learn_parm_s {
|
||||
void (*kpinfo_cb)(void*, const char *);
|
||||
void *kpinfo_cb_arg;
|
||||
void (*certinfo_cb)(void*, const char *);
|
||||
void *certinfo_cb_arg;
|
||||
};
|
||||
|
||||
struct inq_needpin_s {
|
||||
ASSUAN_CONTEXT ctx;
|
||||
int (*getpin_cb)(void *, const char *, char*, size_t);
|
||||
void *getpin_cb_arg;
|
||||
};
|
||||
|
||||
struct membuf {
|
||||
size_t len;
|
||||
size_t size;
|
||||
char *buf;
|
||||
int out_of_core;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* A simple implementation of a dynamic buffer. Use init_membuf() to
|
||||
create a buffer, put_membuf to append bytes and get_membuf to
|
||||
release and return the buffer. Allocation errors are detected but
|
||||
only returned at the final get_membuf(), this helps not to clutter
|
||||
the code with out of core checks. */
|
||||
|
||||
static void
|
||||
init_membuf (struct membuf *mb, int initiallen)
|
||||
{
|
||||
mb->len = 0;
|
||||
mb->size = initiallen;
|
||||
mb->out_of_core = 0;
|
||||
mb->buf = xtrymalloc (initiallen);
|
||||
if (!mb->buf)
|
||||
mb->out_of_core = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
put_membuf (struct membuf *mb, const void *buf, size_t len)
|
||||
{
|
||||
if (mb->out_of_core)
|
||||
return;
|
||||
|
||||
if (mb->len + len >= mb->size)
|
||||
{
|
||||
char *p;
|
||||
|
||||
mb->size += len + 1024;
|
||||
p = xtryrealloc (mb->buf, mb->size);
|
||||
if (!p)
|
||||
{
|
||||
mb->out_of_core = 1;
|
||||
return;
|
||||
}
|
||||
mb->buf = p;
|
||||
}
|
||||
memcpy (mb->buf + mb->len, buf, len);
|
||||
mb->len += len;
|
||||
}
|
||||
|
||||
static void *
|
||||
get_membuf (struct membuf *mb, size_t *len)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (mb->out_of_core)
|
||||
{
|
||||
xfree (mb->buf);
|
||||
mb->buf = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = mb->buf;
|
||||
*len = mb->len;
|
||||
mb->buf = NULL;
|
||||
mb->out_of_core = 1; /* don't allow a reuse */
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int
|
||||
unlock_scd (int rc)
|
||||
{
|
||||
#ifdef USE_GNU_PTH
|
||||
if (!pth_mutex_release (&scd_lock))
|
||||
{
|
||||
log_error ("failed to release the SCD lock\n");
|
||||
if (!rc)
|
||||
rc = GNUPG_Internal_Error;
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Fork off the SCdaemon if this has not already been done */
|
||||
static int
|
||||
start_scd (void)
|
||||
{
|
||||
int rc;
|
||||
const char *pgmname;
|
||||
ASSUAN_CONTEXT ctx;
|
||||
const char *argv[3];
|
||||
int no_close_list[3];
|
||||
int i;
|
||||
|
||||
#ifdef USE_GNU_PTH
|
||||
if (!pth_mutex_acquire (&scd_lock, 0, NULL))
|
||||
{
|
||||
log_error ("failed to acquire the SCD lock\n");
|
||||
return GNUPG_Internal_Error;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (scd_ctx)
|
||||
return 0; /* No need to serialize things because the agent is
|
||||
expected to tun as a single-thread (or may be in
|
||||
future using libpth) */
|
||||
|
||||
if (opt.verbose)
|
||||
log_info ("no running SCdaemon - starting it\n");
|
||||
|
||||
if (fflush (NULL))
|
||||
{
|
||||
log_error ("error flushing pending output: %s\n", strerror (errno));
|
||||
return unlock_scd (seterr (Write_Error));
|
||||
}
|
||||
|
||||
if (!opt.scdaemon_program || !*opt.scdaemon_program)
|
||||
opt.scdaemon_program = GNUPG_DEFAULT_SCDAEMON;
|
||||
if ( !(pgmname = strrchr (opt.scdaemon_program, '/')))
|
||||
pgmname = opt.scdaemon_program;
|
||||
else
|
||||
pgmname++;
|
||||
|
||||
argv[0] = pgmname;
|
||||
argv[1] = "--server";
|
||||
argv[2] = NULL;
|
||||
|
||||
i=0;
|
||||
if (!opt.running_detached)
|
||||
{
|
||||
if (log_get_fd () != -1)
|
||||
no_close_list[i++] = log_get_fd ();
|
||||
no_close_list[i++] = fileno (stderr);
|
||||
}
|
||||
no_close_list[i] = -1;
|
||||
|
||||
/* connect to the pinentry and perform initial handshaking */
|
||||
rc = assuan_pipe_connect (&ctx, opt.scdaemon_program, (char**)argv,
|
||||
no_close_list);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("can't connect to the SCdaemon: %s\n",
|
||||
assuan_strerror (rc));
|
||||
return unlock_scd (seterr (No_Scdaemon));
|
||||
}
|
||||
scd_ctx = ctx;
|
||||
|
||||
if (DBG_ASSUAN)
|
||||
log_debug ("connection to SCdaemon established\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static AssuanError
|
||||
learn_status_cb (void *opaque, const char *line)
|
||||
{
|
||||
struct learn_parm_s *parm = opaque;
|
||||
const char *keyword = line;
|
||||
int keywordlen;
|
||||
|
||||
for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
|
||||
;
|
||||
while (spacep (line))
|
||||
line++;
|
||||
if (keywordlen == 8 && !memcmp (keyword, "CERTINFO", keywordlen))
|
||||
{
|
||||
parm->certinfo_cb (parm->certinfo_cb_arg, line);
|
||||
}
|
||||
else if (keywordlen == 11 && !memcmp (keyword, "KEYPAIRINFO", keywordlen))
|
||||
{
|
||||
parm->kpinfo_cb (parm->kpinfo_cb_arg, line);
|
||||
}
|
||||
else if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
|
||||
{
|
||||
log_debug ("learn_status_cb: serialno `%s'\n", line);
|
||||
}
|
||||
else
|
||||
log_debug ("learn_status_cb: ignoring `%.*s'\n", keywordlen, keyword);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perform the learn command and return a list of all private keys
|
||||
stored on the card. */
|
||||
int
|
||||
agent_card_learn (void (*kpinfo_cb)(void*, const char *),
|
||||
void *kpinfo_cb_arg,
|
||||
void (*certinfo_cb)(void*, const char *),
|
||||
void *certinfo_cb_arg)
|
||||
{
|
||||
int rc;
|
||||
struct learn_parm_s parm;
|
||||
|
||||
rc = start_scd ();
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
memset (&parm, 0, sizeof parm);
|
||||
parm.kpinfo_cb = kpinfo_cb;
|
||||
parm.kpinfo_cb_arg = kpinfo_cb_arg;
|
||||
parm.certinfo_cb = certinfo_cb;
|
||||
parm.certinfo_cb_arg = certinfo_cb_arg;
|
||||
rc = assuan_transact (scd_ctx, "LEARN --force",
|
||||
NULL, NULL, NULL, NULL,
|
||||
learn_status_cb, &parm);
|
||||
if (rc)
|
||||
return unlock_scd (map_assuan_err (rc));
|
||||
|
||||
return unlock_scd (0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static AssuanError
|
||||
get_serialno_cb (void *opaque, const char *line)
|
||||
{
|
||||
char **serialno = opaque;
|
||||
const char *keyword = line;
|
||||
const char *s;
|
||||
int keywordlen, n;
|
||||
|
||||
for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
|
||||
;
|
||||
while (spacep (line))
|
||||
line++;
|
||||
|
||||
if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
|
||||
{
|
||||
if (*serialno)
|
||||
return ASSUAN_Unexpected_Status;
|
||||
for (n=0,s=line; hexdigitp (s); s++, n++)
|
||||
;
|
||||
if (!n || (n&1)|| !(spacep (s) || !*s) )
|
||||
return ASSUAN_Invalid_Status;
|
||||
*serialno = xtrymalloc (n+1);
|
||||
if (!*serialno)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
memcpy (*serialno, line, n);
|
||||
(*serialno)[n] = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the serial number of the card or an appropriate error. The
|
||||
serial number is returned as a hexstring. */
|
||||
int
|
||||
agent_card_serialno (char **r_serialno)
|
||||
{
|
||||
int rc;
|
||||
char *serialno = NULL;
|
||||
|
||||
rc = start_scd ();
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Hmm, do we really need this reset - scddaemon should do this or
|
||||
we can do this if we for some reason figure out that the
|
||||
operation might have failed due to a missing RESET. Hmmm, I feel
|
||||
this is really SCdaemon's duty */
|
||||
rc = assuan_transact (scd_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return unlock_scd (map_assuan_err (rc));
|
||||
|
||||
rc = assuan_transact (scd_ctx, "SERIALNO",
|
||||
NULL, NULL, NULL, NULL,
|
||||
get_serialno_cb, &serialno);
|
||||
if (rc)
|
||||
{
|
||||
xfree (serialno);
|
||||
return unlock_scd (map_assuan_err (rc));
|
||||
}
|
||||
*r_serialno = serialno;
|
||||
return unlock_scd (0);
|
||||
}
|
||||
|
||||
|
||||
static AssuanError
|
||||
membuf_data_cb (void *opaque, const void *buffer, size_t length)
|
||||
{
|
||||
struct membuf *data = opaque;
|
||||
|
||||
if (buffer)
|
||||
put_membuf (data, buffer, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Handle the NEEDPIN inquiry. */
|
||||
static AssuanError
|
||||
inq_needpin (void *opaque, const char *line)
|
||||
{
|
||||
struct inq_needpin_s *parm = opaque;
|
||||
char *pin;
|
||||
size_t pinlen;
|
||||
int rc;
|
||||
|
||||
if (!(!strncmp (line, "NEEDPIN", 7) && (line[7] == ' ' || !line[7])))
|
||||
{
|
||||
log_error ("unsupported inquiry `%s'\n", line);
|
||||
return ASSUAN_Inquire_Unknown;
|
||||
}
|
||||
line += 7;
|
||||
|
||||
pinlen = 90;
|
||||
pin = gcry_malloc_secure (pinlen);
|
||||
if (!pin)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
|
||||
rc = parm->getpin_cb (parm->getpin_cb_arg, line, pin, pinlen);
|
||||
if (rc)
|
||||
rc = ASSUAN_Canceled;
|
||||
if (!rc)
|
||||
rc = assuan_send_data (parm->ctx, pin, pinlen);
|
||||
xfree (pin);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Create a signature using the current card */
|
||||
int
|
||||
agent_card_pksign (const char *keyid,
|
||||
int (*getpin_cb)(void *, const char *, char*, size_t),
|
||||
void *getpin_cb_arg,
|
||||
const unsigned char *indata, size_t indatalen,
|
||||
char **r_buf, size_t *r_buflen)
|
||||
{
|
||||
int rc, i;
|
||||
char *p, line[ASSUAN_LINELENGTH];
|
||||
struct membuf data;
|
||||
struct inq_needpin_s inqparm;
|
||||
size_t len;
|
||||
unsigned char *sigbuf;
|
||||
size_t sigbuflen;
|
||||
|
||||
*r_buf = NULL;
|
||||
rc = start_scd ();
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (indatalen*2 + 50 > DIM(line))
|
||||
return unlock_scd (seterr (General_Error));
|
||||
|
||||
sprintf (line, "SETDATA ");
|
||||
p = line + strlen (line);
|
||||
for (i=0; i < indatalen ; i++, p += 2 )
|
||||
sprintf (p, "%02X", indata[i]);
|
||||
rc = assuan_transact (scd_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return unlock_scd (map_assuan_err (rc));
|
||||
|
||||
init_membuf (&data, 1024);
|
||||
inqparm.ctx = scd_ctx;
|
||||
inqparm.getpin_cb = getpin_cb;
|
||||
inqparm.getpin_cb_arg = getpin_cb_arg;
|
||||
snprintf (line, DIM(line)-1, "PKSIGN %s", keyid);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (scd_ctx, line,
|
||||
membuf_data_cb, &data,
|
||||
inq_needpin, &inqparm,
|
||||
NULL, NULL);
|
||||
if (rc)
|
||||
{
|
||||
xfree (get_membuf (&data, &len));
|
||||
return unlock_scd (map_assuan_err (rc));
|
||||
}
|
||||
sigbuf = get_membuf (&data, &sigbuflen);
|
||||
|
||||
/* create an S-expression from it which is formatted like this:
|
||||
"(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))" */
|
||||
*r_buflen = 21 + 11 + sigbuflen + 4;
|
||||
*r_buf = xtrymalloc (*r_buflen);
|
||||
if (!*r_buf)
|
||||
{
|
||||
xfree (*r_buf);
|
||||
return unlock_scd (GNUPG_Out_Of_Core);
|
||||
}
|
||||
p = stpcpy (*r_buf, "(7:sig-val(3:rsa(1:s" );
|
||||
sprintf (p, "%u:", (unsigned int)sigbuflen);
|
||||
p += strlen (p);
|
||||
memcpy (p, sigbuf, sigbuflen);
|
||||
p += sigbuflen;
|
||||
strcpy (p, ")))");
|
||||
xfree (sigbuf);
|
||||
|
||||
assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL));
|
||||
return unlock_scd (0);
|
||||
}
|
||||
|
||||
/* Decipher INDATA using the current card. Note that the returned value is */
|
||||
int
|
||||
agent_card_pkdecrypt (const char *keyid,
|
||||
int (*getpin_cb)(void *, const char *, char*, size_t),
|
||||
void *getpin_cb_arg,
|
||||
const unsigned char *indata, size_t indatalen,
|
||||
char **r_buf, size_t *r_buflen)
|
||||
{
|
||||
int rc, i;
|
||||
char *p, line[ASSUAN_LINELENGTH];
|
||||
struct membuf data;
|
||||
struct inq_needpin_s inqparm;
|
||||
size_t len;
|
||||
|
||||
*r_buf = NULL;
|
||||
rc = start_scd ();
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* FIXME: use secure memory where appropriate */
|
||||
if (indatalen*2 + 50 > DIM(line))
|
||||
return unlock_scd (seterr (General_Error));
|
||||
|
||||
sprintf (line, "SETDATA ");
|
||||
p = line + strlen (line);
|
||||
for (i=0; i < indatalen ; i++, p += 2 )
|
||||
sprintf (p, "%02X", indata[i]);
|
||||
rc = assuan_transact (scd_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return unlock_scd (map_assuan_err (rc));
|
||||
|
||||
init_membuf (&data, 1024);
|
||||
inqparm.ctx = scd_ctx;
|
||||
inqparm.getpin_cb = getpin_cb;
|
||||
inqparm.getpin_cb_arg = getpin_cb_arg;
|
||||
snprintf (line, DIM(line)-1, "PKDECRYPT %s", keyid);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (scd_ctx, line,
|
||||
membuf_data_cb, &data,
|
||||
inq_needpin, &inqparm,
|
||||
NULL, NULL);
|
||||
if (rc)
|
||||
{
|
||||
xfree (get_membuf (&data, &len));
|
||||
return unlock_scd (map_assuan_err (rc));
|
||||
}
|
||||
*r_buf = get_membuf (&data, r_buflen);
|
||||
if (!*r_buf)
|
||||
return unlock_scd (GNUPG_Out_Of_Core);
|
||||
|
||||
return unlock_scd (0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Read a certificate with ID into R_BUF and R_BUFLEN. */
|
||||
int
|
||||
agent_card_readcert (const char *id, char **r_buf, size_t *r_buflen)
|
||||
{
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct membuf data;
|
||||
size_t len;
|
||||
|
||||
*r_buf = NULL;
|
||||
rc = start_scd ();
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
init_membuf (&data, 1024);
|
||||
snprintf (line, DIM(line)-1, "READCERT %s", id);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (scd_ctx, line,
|
||||
membuf_data_cb, &data,
|
||||
NULL, NULL,
|
||||
NULL, NULL);
|
||||
if (rc)
|
||||
{
|
||||
xfree (get_membuf (&data, &len));
|
||||
return unlock_scd (map_assuan_err (rc));
|
||||
}
|
||||
*r_buf = get_membuf (&data, r_buflen);
|
||||
if (!*r_buf)
|
||||
return unlock_scd (GNUPG_Out_Of_Core);
|
||||
|
||||
return unlock_scd (0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Read a key with ID and return it in an allocate buffer pointed to
|
||||
by r_BUF as a valid S-expression. */
|
||||
int
|
||||
agent_card_readkey (const char *id, unsigned char **r_buf)
|
||||
{
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct membuf data;
|
||||
size_t len, buflen;
|
||||
|
||||
*r_buf = NULL;
|
||||
rc = start_scd ();
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
init_membuf (&data, 1024);
|
||||
snprintf (line, DIM(line)-1, "READKEY %s", id);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (scd_ctx, line,
|
||||
membuf_data_cb, &data,
|
||||
NULL, NULL,
|
||||
NULL, NULL);
|
||||
if (rc)
|
||||
{
|
||||
xfree (get_membuf (&data, &len));
|
||||
return unlock_scd (map_assuan_err (rc));
|
||||
}
|
||||
*r_buf = get_membuf (&data, &buflen);
|
||||
if (!*r_buf)
|
||||
return unlock_scd (GNUPG_Out_Of_Core);
|
||||
|
||||
if (!gcry_sexp_canon_len (*r_buf, buflen, NULL, NULL))
|
||||
{
|
||||
xfree (*r_buf); *r_buf = NULL;
|
||||
return unlock_scd (GNUPG_Invalid_Value);
|
||||
}
|
||||
|
||||
return unlock_scd (0);
|
||||
}
|
||||
|
||||
|
||||
|
697
agent/command.c
697
agent/command.c
@ -1,697 +0,0 @@
|
||||
/* command.c - gpg-agent command handler
|
||||
* Copyright (C) 2001, 2002 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
|
||||
*/
|
||||
|
||||
/* FIXME: we should not use the default assuan buffering but setup
|
||||
some buffering in secure mempory to protect session keys etc. */
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "agent.h"
|
||||
#include "../assuan/assuan.h"
|
||||
|
||||
/* maximum allowed size of the inquired ciphertext */
|
||||
#define MAXLEN_CIPHERTEXT 4096
|
||||
/* maximum allowed size of the key parameters */
|
||||
#define MAXLEN_KEYPARAM 1024
|
||||
|
||||
#define set_error(e,t) assuan_set_error (ctx, ASSUAN_ ## e, (t))
|
||||
|
||||
|
||||
#if MAX_DIGEST_LEN < 20
|
||||
#error MAX_DIGEST_LEN shorter than keygrip
|
||||
#endif
|
||||
|
||||
/* Data used to associate an Assuan context with local server data */
|
||||
struct server_local_s {
|
||||
ASSUAN_CONTEXT assuan_ctx;
|
||||
int message_fd;
|
||||
int use_cache_for_signing;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
reset_notify (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
|
||||
memset (ctrl->keygrip, 0, 20);
|
||||
ctrl->have_keygrip = 0;
|
||||
ctrl->digest.valuelen = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Check whether the option NAME appears in LINE */
|
||||
static int
|
||||
has_option (const char *line, const char *name)
|
||||
{
|
||||
const char *s;
|
||||
int n = strlen (name);
|
||||
|
||||
s = strstr (line, name);
|
||||
return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ISTRUSTED <hexstring_with_fingerprint>
|
||||
|
||||
Return OK when we have an entry with this fingerprint in our
|
||||
trustlist */
|
||||
static int
|
||||
cmd_istrusted (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
int rc, n, i;
|
||||
char *p;
|
||||
char fpr[41];
|
||||
|
||||
/* parse the fingerprint value */
|
||||
for (p=line,n=0; hexdigitp (p); p++, n++)
|
||||
;
|
||||
if (*p || !(n == 40 || n == 32))
|
||||
return set_error (Parameter_Error, "invalid fingerprint");
|
||||
i = 0;
|
||||
if (n==32)
|
||||
{
|
||||
strcpy (fpr, "00000000");
|
||||
i += 8;
|
||||
}
|
||||
for (p=line; i < 40; p++, i++)
|
||||
fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
|
||||
fpr[i] = 0;
|
||||
rc = agent_istrusted (fpr);
|
||||
if (!rc)
|
||||
return 0;
|
||||
else if (rc == -1)
|
||||
return ASSUAN_Not_Trusted;
|
||||
else
|
||||
{
|
||||
log_error ("command is_trusted failed: %s\n", gnupg_strerror (rc));
|
||||
return map_to_assuan_status (rc);
|
||||
}
|
||||
}
|
||||
|
||||
/* LISTTRUSTED
|
||||
|
||||
List all entries from the trustlist */
|
||||
static int
|
||||
cmd_listtrusted (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
int rc = agent_listtrusted (ctx);
|
||||
if (rc)
|
||||
log_error ("command listtrusted failed: %s\n", gnupg_strerror (rc));
|
||||
return map_to_assuan_status (rc);
|
||||
}
|
||||
|
||||
|
||||
/* MARKTRUSTED <hexstring_with_fingerprint> <flag> <display_name>
|
||||
|
||||
Store a new key in into the trustlist*/
|
||||
static int
|
||||
cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
int rc, n, i;
|
||||
char *p;
|
||||
char fpr[41];
|
||||
int flag;
|
||||
|
||||
/* parse the fingerprint value */
|
||||
for (p=line,n=0; hexdigitp (p); p++, n++)
|
||||
;
|
||||
if (!spacep (p) || !(n == 40 || n == 32))
|
||||
return set_error (Parameter_Error, "invalid fingerprint");
|
||||
i = 0;
|
||||
if (n==32)
|
||||
{
|
||||
strcpy (fpr, "00000000");
|
||||
i += 8;
|
||||
}
|
||||
for (p=line; i < 40; p++, i++)
|
||||
fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
|
||||
fpr[i] = 0;
|
||||
|
||||
while (spacep (p))
|
||||
p++;
|
||||
flag = *p++;
|
||||
if ( (flag != 'S' && flag != 'P') || !spacep (p) )
|
||||
return set_error (Parameter_Error, "invalid flag - must be P or S");
|
||||
while (spacep (p))
|
||||
p++;
|
||||
|
||||
rc = agent_marktrusted (p, fpr, flag);
|
||||
if (rc)
|
||||
log_error ("command marktrusted failed: %s\n", gnupg_strerror (rc));
|
||||
return map_to_assuan_status (rc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* HAVEKEY <hexstring_with_keygrip>
|
||||
|
||||
Return success when the secret key is available */
|
||||
static int
|
||||
cmd_havekey (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
int n;
|
||||
char *p;
|
||||
unsigned char buf[20];
|
||||
|
||||
/* parse the hash value */
|
||||
for (p=line,n=0; hexdigitp (p); p++, n++)
|
||||
;
|
||||
if (*p)
|
||||
return set_error (Parameter_Error, "invalid hexstring");
|
||||
if ((n&1))
|
||||
return set_error (Parameter_Error, "odd number of digits");
|
||||
n /= 2;
|
||||
if (n != 20)
|
||||
return set_error (Parameter_Error, "invalid length of keygrip");
|
||||
|
||||
for (p=line, n=0; n < 20; p += 2, n++)
|
||||
buf[n] = xtoi_2 (p);
|
||||
|
||||
if (agent_key_available (buf))
|
||||
return ASSUAN_No_Secret_Key;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* SIGKEY <hexstring_with_keygrip>
|
||||
SETKEY <hexstring_with_keygrip>
|
||||
|
||||
Set the key used for a sign or decrypt operation */
|
||||
static int
|
||||
cmd_sigkey (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
int n;
|
||||
char *p;
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
unsigned char *buf;
|
||||
|
||||
/* parse the hash value */
|
||||
for (p=line,n=0; hexdigitp (p); p++, n++)
|
||||
;
|
||||
if (*p)
|
||||
return set_error (Parameter_Error, "invalid hexstring");
|
||||
if ((n&1))
|
||||
return set_error (Parameter_Error, "odd number of digits");
|
||||
n /= 2;
|
||||
if (n != 20)
|
||||
return set_error (Parameter_Error, "invalid length of keygrip");
|
||||
|
||||
buf = ctrl->keygrip;
|
||||
for (p=line, n=0; n < 20; p += 2, n++)
|
||||
buf[n] = xtoi_2 (p);
|
||||
ctrl->have_keygrip = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SETHASH <algonumber> <hexstring>
|
||||
|
||||
The client can use this command to tell the server about the data
|
||||
(which usually is a hash) to be signed. */
|
||||
static int
|
||||
cmd_sethash (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
int n;
|
||||
char *p;
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
unsigned char *buf;
|
||||
char *endp;
|
||||
int algo;
|
||||
|
||||
/* parse the algo number and check it */
|
||||
algo = (int)strtoul (line, &endp, 10);
|
||||
for (line = endp; *line == ' ' || *line == '\t'; line++)
|
||||
;
|
||||
if (!algo || gcry_md_test_algo (algo))
|
||||
return set_error (Unsupported_Algorithm, NULL);
|
||||
ctrl->digest.algo = algo;
|
||||
|
||||
/* parse the hash value */
|
||||
for (p=line,n=0; hexdigitp (p); p++, n++)
|
||||
;
|
||||
if (*p)
|
||||
return set_error (Parameter_Error, "invalid hexstring");
|
||||
if ((n&1))
|
||||
return set_error (Parameter_Error, "odd number of digits");
|
||||
n /= 2;
|
||||
if (n != 16 && n != 20 && n != 24 && n != 32)
|
||||
return set_error (Parameter_Error, "unsupported length of hash");
|
||||
if (n > MAX_DIGEST_LEN)
|
||||
return set_error (Parameter_Error, "hash value to long");
|
||||
|
||||
buf = ctrl->digest.value;
|
||||
ctrl->digest.valuelen = n;
|
||||
for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++)
|
||||
buf[n] = xtoi_2 (p);
|
||||
for (; n < ctrl->digest.valuelen; n++)
|
||||
buf[n] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* PKSIGN <options>
|
||||
|
||||
Perform the actual sign operation. Neither input nor output are
|
||||
sensitive to eavesdropping */
|
||||
static int
|
||||
cmd_pksign (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
int rc;
|
||||
int ignore_cache = 0;
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
|
||||
if (opt.ignore_cache_for_signing)
|
||||
ignore_cache = 1;
|
||||
else if (!ctrl->server_local->use_cache_for_signing)
|
||||
ignore_cache = 1;
|
||||
|
||||
rc = agent_pksign (ctrl, assuan_get_data_fp (ctx), ignore_cache);
|
||||
if (rc)
|
||||
log_error ("command pksign failed: %s\n", gnupg_strerror (rc));
|
||||
return map_to_assuan_status (rc);
|
||||
}
|
||||
|
||||
/* PKDECRYPT <options>
|
||||
|
||||
Perform the actual decrypt operation. Input is not
|
||||
sensitive to eavesdropping */
|
||||
static int
|
||||
cmd_pkdecrypt (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
int rc;
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
char *value;
|
||||
size_t valuelen;
|
||||
|
||||
/* First inquire the data to decrypt */
|
||||
rc = assuan_inquire (ctx, "CIPHERTEXT",
|
||||
&value, &valuelen, MAXLEN_CIPHERTEXT);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = agent_pkdecrypt (ctrl, value, valuelen, assuan_get_data_fp (ctx));
|
||||
xfree (value);
|
||||
if (rc)
|
||||
log_error ("command pkdecrypt failed: %s\n", gnupg_strerror (rc));
|
||||
return map_to_assuan_status (rc);
|
||||
}
|
||||
|
||||
|
||||
/* GENKEY
|
||||
|
||||
Generate a new key, store the secret part and return the public
|
||||
part. Here is an example transaction:
|
||||
|
||||
C: GENKEY
|
||||
S: INQUIRE KEYPARM
|
||||
C: D (genkey (rsa (nbits 1024)))
|
||||
C: END
|
||||
S: D (public-key
|
||||
S: D (rsa (n 326487324683264) (e 10001)))
|
||||
S OK key created
|
||||
*/
|
||||
|
||||
static int
|
||||
cmd_genkey (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
int rc;
|
||||
char *value;
|
||||
size_t valuelen;
|
||||
|
||||
/* First inquire the parameters */
|
||||
rc = assuan_inquire (ctx, "KEYPARAM", &value, &valuelen, MAXLEN_KEYPARAM);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = agent_genkey (ctrl, value, valuelen, assuan_get_data_fp (ctx));
|
||||
xfree (value);
|
||||
if (rc)
|
||||
log_error ("command genkey failed: %s\n", gnupg_strerror (rc));
|
||||
return map_to_assuan_status (rc);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
plus_to_blank (char *s)
|
||||
{
|
||||
for (; *s; s++)
|
||||
{
|
||||
if (*s == '+')
|
||||
*s = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
/* GET_PASSPHRASE <cache_id> [<error_message> <prompt> <description>]
|
||||
|
||||
This function is usually used to ask for a passphrase to be used
|
||||
for conventional encryption, but may also be used by programs which
|
||||
need specal handling of passphrases. This command uses a syntax
|
||||
which helps clients to use the agent with minimum effort. The
|
||||
agent either returns with an error or with a OK followed by the hex
|
||||
encoded passphrase. Note that the length of the strings is
|
||||
implicitly limited by the maximum length of a command.
|
||||
*/
|
||||
|
||||
static int
|
||||
cmd_get_passphrase (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
int rc;
|
||||
const char *pw;
|
||||
char *response;
|
||||
char *cacheid = NULL, *desc = NULL, *prompt = NULL, *errtext = NULL;
|
||||
char *p;
|
||||
void *cache_marker;
|
||||
|
||||
/* parse the stuff */
|
||||
for (p=line; *p == ' '; p++)
|
||||
;
|
||||
cacheid = p;
|
||||
p = strchr (cacheid, ' ');
|
||||
if (p)
|
||||
{
|
||||
*p++ = 0;
|
||||
while (*p == ' ')
|
||||
p++;
|
||||
errtext = p;
|
||||
p = strchr (errtext, ' ');
|
||||
if (p)
|
||||
{
|
||||
*p++ = 0;
|
||||
while (*p == ' ')
|
||||
p++;
|
||||
prompt = p;
|
||||
p = strchr (prompt, ' ');
|
||||
if (p)
|
||||
{
|
||||
*p++ = 0;
|
||||
while (*p == ' ')
|
||||
p++;
|
||||
desc = p;
|
||||
p = strchr (desc, ' ');
|
||||
if (p)
|
||||
*p = 0; /* ignore garbage */
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!cacheid || !*cacheid || strlen (cacheid) > 50)
|
||||
return set_error (Parameter_Error, "invalid length of cacheID");
|
||||
if (!desc)
|
||||
return set_error (Parameter_Error, "no description given");
|
||||
|
||||
if (!strcmp (cacheid, "X"))
|
||||
cacheid = NULL;
|
||||
if (!strcmp (errtext, "X"))
|
||||
errtext = NULL;
|
||||
if (!strcmp (prompt, "X"))
|
||||
prompt = NULL;
|
||||
if (!strcmp (desc, "X"))
|
||||
desc = NULL;
|
||||
|
||||
/* Note: we store the hexified versions in the cache. */
|
||||
pw = cacheid ? agent_get_cache (cacheid, &cache_marker) : NULL;
|
||||
if (pw)
|
||||
{
|
||||
assuan_begin_confidential (ctx);
|
||||
rc = assuan_set_okay_line (ctx, pw);
|
||||
agent_unlock_cache_entry (&cache_marker);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Note, that we only need to replace the + characters and
|
||||
should leave the other escaping in place because the escaped
|
||||
string is send verbatim to the pinentry which does the
|
||||
unescaping (but not the + replacing) */
|
||||
if (errtext)
|
||||
plus_to_blank (errtext);
|
||||
if (prompt)
|
||||
plus_to_blank (prompt);
|
||||
if (desc)
|
||||
plus_to_blank (desc);
|
||||
|
||||
rc = agent_get_passphrase (&response, desc, prompt, errtext);
|
||||
if (!rc)
|
||||
{
|
||||
if (cacheid)
|
||||
agent_put_cache (cacheid, response, 0);
|
||||
assuan_begin_confidential (ctx);
|
||||
rc = assuan_set_okay_line (ctx, response);
|
||||
xfree (response);
|
||||
}
|
||||
}
|
||||
|
||||
if (rc)
|
||||
log_error ("command get_passphrase failed: %s\n", gnupg_strerror (rc));
|
||||
return map_to_assuan_status (rc);
|
||||
}
|
||||
|
||||
|
||||
/* CLEAR_PASSPHRASE <cache_id>
|
||||
|
||||
may be used to invalidate the cache entry for a passphrase. The
|
||||
function returns with OK even when there is no cached passphrase.
|
||||
*/
|
||||
|
||||
static int
|
||||
cmd_clear_passphrase (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
char *cacheid = NULL;
|
||||
char *p;
|
||||
|
||||
/* parse the stuff */
|
||||
for (p=line; *p == ' '; p++)
|
||||
;
|
||||
cacheid = p;
|
||||
p = strchr (cacheid, ' ');
|
||||
if (p)
|
||||
*p = 0; /* ignore garbage */
|
||||
if (!cacheid || !*cacheid || strlen (cacheid) > 50)
|
||||
return set_error (Parameter_Error, "invalid length of cacheID");
|
||||
|
||||
agent_put_cache (cacheid, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* LEARN [--send]
|
||||
|
||||
Learn something about the currently inserted smartcard. With
|
||||
--send the new certificates are send back. */
|
||||
static int
|
||||
cmd_learn (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = agent_handle_learn (has_option (line, "--send")? ctx : NULL);
|
||||
if (rc)
|
||||
log_error ("command learn failed: %s\n", gnupg_strerror (rc));
|
||||
return map_to_assuan_status (rc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value)
|
||||
{
|
||||
CTRL ctrl = assuan_get_pointer (ctx);
|
||||
|
||||
/* FIXME: We should not change opt. here. It is not a problem right
|
||||
now but as soon as we are allowing concurrent connections we mess
|
||||
things up */
|
||||
if (!strcmp (key, "display"))
|
||||
{
|
||||
if (opt.display)
|
||||
free (opt.display);
|
||||
opt.display = strdup (value);
|
||||
if (!opt.display)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
}
|
||||
else if (!strcmp (key, "ttyname"))
|
||||
{
|
||||
if (opt.ttyname)
|
||||
free (opt.ttyname);
|
||||
opt.ttyname = strdup (value);
|
||||
if (!opt.ttyname)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
}
|
||||
else if (!strcmp (key, "ttytype"))
|
||||
{
|
||||
if (opt.ttytype)
|
||||
free (opt.ttytype);
|
||||
opt.ttytype = strdup (value);
|
||||
if (!opt.ttytype)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
}
|
||||
else if (!strcmp (key, "lc-ctype"))
|
||||
{
|
||||
if (opt.lc_ctype)
|
||||
free (opt.lc_ctype);
|
||||
opt.lc_ctype = strdup (value);
|
||||
if (!opt.lc_ctype)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
}
|
||||
else if (!strcmp (key, "lc-messages"))
|
||||
{
|
||||
if (opt.lc_messages)
|
||||
free (opt.lc_messages);
|
||||
opt.lc_messages = strdup (value);
|
||||
if (!opt.lc_messages)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
}
|
||||
else if (!strcmp (key, "use-cache-for-signing"))
|
||||
ctrl->server_local->use_cache_for_signing = *value? atoi (value) : 0;
|
||||
else
|
||||
return ASSUAN_Invalid_Option;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Tell the assuan library about our commands */
|
||||
static int
|
||||
register_commands (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
static struct {
|
||||
const char *name;
|
||||
int cmd_id;
|
||||
int (*handler)(ASSUAN_CONTEXT, char *line);
|
||||
} table[] = {
|
||||
{ "ISTRUSTED", 0, cmd_istrusted },
|
||||
{ "HAVEKEY", 0, cmd_havekey },
|
||||
{ "SIGKEY", 0, cmd_sigkey },
|
||||
{ "SETKEY", 0, cmd_sigkey },
|
||||
{ "SETHASH", 0, cmd_sethash },
|
||||
{ "PKSIGN", 0, cmd_pksign },
|
||||
{ "PKDECRYPT", 0, cmd_pkdecrypt },
|
||||
{ "GENKEY", 0, cmd_genkey },
|
||||
{ "GET_PASSPHRASE",0, cmd_get_passphrase },
|
||||
{ "CLEAR_PASSPHRASE",0, cmd_clear_passphrase },
|
||||
{ "LISTTRUSTED", 0, cmd_listtrusted },
|
||||
{ "MARKTRUSTED", 0, cmd_marktrusted },
|
||||
{ "LEARN", 0, cmd_learn },
|
||||
{ "", ASSUAN_CMD_INPUT, NULL },
|
||||
{ "", ASSUAN_CMD_OUTPUT, NULL },
|
||||
{ NULL }
|
||||
};
|
||||
int i, j, rc;
|
||||
|
||||
for (i=j=0; table[i].name; i++)
|
||||
{
|
||||
rc = assuan_register_command (ctx,
|
||||
table[i].cmd_id? table[i].cmd_id
|
||||
: (ASSUAN_CMD_USER + j++),
|
||||
table[i].name, table[i].handler);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
assuan_register_reset_notify (ctx, reset_notify);
|
||||
assuan_register_option_handler (ctx, option_handler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Startup the server. If LISTEN_FD and FD is given as -1, this is a simple
|
||||
piper server, otherwise it is a regular server */
|
||||
void
|
||||
start_command_handler (int listen_fd, int fd)
|
||||
{
|
||||
int rc;
|
||||
ASSUAN_CONTEXT ctx;
|
||||
struct server_control_s ctrl;
|
||||
|
||||
memset (&ctrl, 0, sizeof ctrl);
|
||||
|
||||
if (listen_fd == -1 && fd == -1)
|
||||
{
|
||||
int filedes[2];
|
||||
|
||||
filedes[0] = 0;
|
||||
filedes[1] = 1;
|
||||
rc = assuan_init_pipe_server (&ctx, filedes);
|
||||
}
|
||||
else if (listen_fd != -1)
|
||||
{
|
||||
rc = assuan_init_socket_server (&ctx, listen_fd);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = assuan_init_connected_socket_server (&ctx, fd);
|
||||
}
|
||||
if (rc)
|
||||
{
|
||||
log_error ("failed to initialize the server: %s\n",
|
||||
assuan_strerror(rc));
|
||||
agent_exit (2);
|
||||
}
|
||||
rc = register_commands (ctx);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("failed to register commands with Assuan: %s\n",
|
||||
assuan_strerror(rc));
|
||||
agent_exit (2);
|
||||
}
|
||||
|
||||
assuan_set_pointer (ctx, &ctrl);
|
||||
ctrl.server_local = xcalloc (1, sizeof *ctrl.server_local);
|
||||
ctrl.server_local->assuan_ctx = ctx;
|
||||
ctrl.server_local->message_fd = -1;
|
||||
ctrl.server_local->use_cache_for_signing = 1;
|
||||
|
||||
if (DBG_ASSUAN)
|
||||
assuan_set_log_stream (ctx, log_get_stream ());
|
||||
|
||||
for (;;)
|
||||
{
|
||||
rc = assuan_accept (ctx);
|
||||
if (rc == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (rc)
|
||||
{
|
||||
log_info ("Assuan accept problem: %s\n", assuan_strerror (rc));
|
||||
break;
|
||||
}
|
||||
|
||||
rc = assuan_process (ctx);
|
||||
if (rc)
|
||||
{
|
||||
log_info ("Assuan processing failed: %s\n", assuan_strerror (rc));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
assuan_deinit_server (ctx);
|
||||
}
|
||||
|
@ -1,305 +0,0 @@
|
||||
/* divert-scd.c - divert operations to the scdaemon
|
||||
* Copyright (C) 2002 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 <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "agent.h"
|
||||
#include "sexp-parse.h"
|
||||
#include "i18n.h"
|
||||
|
||||
|
||||
static int
|
||||
ask_for_card (const unsigned char *shadow_info, char **r_kid)
|
||||
{
|
||||
int rc, i;
|
||||
const unsigned char *s;
|
||||
size_t n;
|
||||
char *serialno;
|
||||
int no_card = 0;
|
||||
char *desc;
|
||||
char *want_sn, *want_kid;
|
||||
int want_sn_displen;
|
||||
|
||||
*r_kid = NULL;
|
||||
s = shadow_info;
|
||||
if (*s != '(')
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
want_sn = xtrymalloc (n*2+1);
|
||||
if (!want_sn)
|
||||
return GNUPG_Out_Of_Core;
|
||||
for (i=0; i < n; i++)
|
||||
sprintf (want_sn+2*i, "%02X", s[i]);
|
||||
s += n;
|
||||
/* We assume that a 20 byte serial number is a standard one which
|
||||
seems to have the property to have a zero in the last nibble. We
|
||||
don't display this '0' because it may confuse the user */
|
||||
want_sn_displen = strlen (want_sn);
|
||||
if (want_sn_displen == 20 && want_sn[19] == '0')
|
||||
want_sn_displen--;
|
||||
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
want_kid = xtrymalloc (n+1);
|
||||
if (!want_kid)
|
||||
{
|
||||
xfree (want_sn);
|
||||
return GNUPG_Out_Of_Core;
|
||||
}
|
||||
memcpy (want_kid, s, n);
|
||||
want_kid[n] = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
rc = agent_card_serialno (&serialno);
|
||||
if (!rc)
|
||||
{
|
||||
log_debug ("detected card with S/N %s\n", serialno);
|
||||
i = strcmp (serialno, want_sn);
|
||||
xfree (serialno);
|
||||
serialno = NULL;
|
||||
if (!i)
|
||||
{
|
||||
xfree (want_sn);
|
||||
*r_kid = want_kid;
|
||||
return 0; /* yes, we have the correct card */
|
||||
}
|
||||
}
|
||||
else if (rc == GNUPG_Card_Not_Present)
|
||||
{
|
||||
log_debug ("no card present\n");
|
||||
rc = 0;
|
||||
no_card = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error ("error accesing card: %s\n", gnupg_strerror (rc));
|
||||
}
|
||||
|
||||
if (!rc)
|
||||
{
|
||||
if (asprintf (&desc,
|
||||
"%s:%%0A%%0A"
|
||||
" \"%.*s\"",
|
||||
no_card? "Please insert the card with serial number"
|
||||
: "Please remove the current card and "
|
||||
"insert the one with serial number",
|
||||
want_sn_displen, want_sn) < 0)
|
||||
{
|
||||
rc = GNUPG_Out_Of_Core;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = agent_get_confirmation (desc, NULL, NULL);
|
||||
free (desc);
|
||||
}
|
||||
}
|
||||
if (rc)
|
||||
{
|
||||
xfree (want_sn);
|
||||
xfree (want_kid);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Put the DIGEST into an DER encoded comtainer and return it in R_VAL. */
|
||||
static int
|
||||
encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo,
|
||||
unsigned char **r_val, size_t *r_len)
|
||||
{
|
||||
byte *frame;
|
||||
byte asn[100];
|
||||
size_t asnlen;
|
||||
|
||||
asnlen = DIM(asn);
|
||||
if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
|
||||
{
|
||||
log_error ("no object identifier for algo %d\n", algo);
|
||||
return GNUPG_Internal_Error;
|
||||
}
|
||||
|
||||
frame = xtrymalloc (asnlen + digestlen);
|
||||
if (!frame)
|
||||
return GNUPG_Out_Of_Core;
|
||||
memcpy (frame, asn, asnlen);
|
||||
memcpy (frame+asnlen, digest, digestlen);
|
||||
if (DBG_CRYPTO)
|
||||
log_printhex ("encoded hash:", frame, asnlen+digestlen);
|
||||
|
||||
*r_val = frame;
|
||||
*r_len = asnlen+digestlen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Callback used to ask for the PIN which should be set into BUF. The
|
||||
buf has been allocated by the caller and is of size MAXBUF which
|
||||
includes the terminating null. The function should return an UTF-8
|
||||
string with the passphrase, the buffer may optionally be padded
|
||||
with arbitrary characters */
|
||||
static int
|
||||
getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
|
||||
{
|
||||
struct pin_entry_info_s *pi;
|
||||
int rc;
|
||||
char *desc;
|
||||
|
||||
assert (!opaque);
|
||||
|
||||
if (maxbuf < 2)
|
||||
return GNUPG_Invalid_Value;
|
||||
|
||||
|
||||
/* FIXME: keep PI and TRIES in OPAQUE. Frankly this is a whole
|
||||
mess because we should call the card's verify function from the
|
||||
pinentry check pin CB. */
|
||||
pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
|
||||
pi->max_length = maxbuf-1;
|
||||
pi->min_digits = 0; /* we want a real passphrase */
|
||||
pi->max_digits = 8;
|
||||
pi->max_tries = 3;
|
||||
|
||||
if ( asprintf (&desc, _("Please enter the PIN%s%s%s to unlock the card"),
|
||||
info? " (`":"",
|
||||
info? info:"",
|
||||
info? "')":"") < 0)
|
||||
desc = NULL;
|
||||
rc = agent_askpin (desc?desc:info, pi);
|
||||
free (desc);
|
||||
if (!rc)
|
||||
{
|
||||
strncpy (buf, pi->pin, maxbuf-1);
|
||||
buf[maxbuf-1] = 0;
|
||||
}
|
||||
xfree (pi);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int
|
||||
divert_pksign (const unsigned char *digest, size_t digestlen, int algo,
|
||||
const unsigned char *shadow_info, unsigned char **r_sig)
|
||||
{
|
||||
int rc;
|
||||
char *kid;
|
||||
size_t siglen;
|
||||
char *sigval;
|
||||
unsigned char *data;
|
||||
size_t ndata;
|
||||
|
||||
rc = ask_for_card (shadow_info, &kid);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = encode_md_for_card (digest, digestlen, algo,
|
||||
&data, &ndata);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = agent_card_pksign (kid, getpin_cb, NULL,
|
||||
data, ndata, &sigval, &siglen);
|
||||
if (!rc)
|
||||
*r_sig = sigval;
|
||||
xfree (data);
|
||||
xfree (kid);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* Decrypt the the value given asn an S-expression in CIPHER using the
|
||||
key identified by SHADOW_INFO and return the plaintext in an
|
||||
allocated buffer in R_BUF. */
|
||||
int
|
||||
divert_pkdecrypt (const unsigned char *cipher,
|
||||
const unsigned char *shadow_info,
|
||||
char **r_buf, size_t *r_len)
|
||||
{
|
||||
int rc;
|
||||
char *kid;
|
||||
const unsigned char *s;
|
||||
size_t n;
|
||||
const unsigned char *ciphertext;
|
||||
size_t ciphertextlen;
|
||||
char *plaintext;
|
||||
size_t plaintextlen;
|
||||
|
||||
s = cipher;
|
||||
if (*s != '(')
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
if (!smatch (&s, n, "enc-val"))
|
||||
return GNUPG_Unknown_Sexp;
|
||||
if (*s != '(')
|
||||
return GNUPG_Unknown_Sexp;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
if (!smatch (&s, n, "rsa"))
|
||||
return GNUPG_Unsupported_Algorithm;
|
||||
if (*s != '(')
|
||||
return GNUPG_Unknown_Sexp;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
if (!smatch (&s, n, "a"))
|
||||
return GNUPG_Unknown_Sexp;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Unknown_Sexp;
|
||||
ciphertext = s;
|
||||
ciphertextlen = n;
|
||||
|
||||
rc = ask_for_card (shadow_info, &kid);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = agent_card_pkdecrypt (kid, getpin_cb, NULL,
|
||||
ciphertext, ciphertextlen,
|
||||
&plaintext, &plaintextlen);
|
||||
if (!rc)
|
||||
{
|
||||
*r_buf = plaintext;
|
||||
*r_len = plaintextlen;
|
||||
}
|
||||
xfree (kid);
|
||||
return rc;
|
||||
}
|
350
agent/findkey.c
350
agent/findkey.c
@ -1,350 +0,0 @@
|
||||
/* findkey.c - locate the secret key
|
||||
* Copyright (C) 2001,02 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 <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "agent.h"
|
||||
|
||||
/* Helper to pass data to the check callback of the unprotect function. */
|
||||
struct try_unprotect_arg_s {
|
||||
const unsigned char *protected_key;
|
||||
unsigned char *unprotected_key;
|
||||
};
|
||||
|
||||
|
||||
|
||||
int
|
||||
agent_write_private_key (const unsigned char *grip,
|
||||
const void *buffer, size_t length, int force)
|
||||
{
|
||||
int i;
|
||||
char *fname;
|
||||
FILE *fp;
|
||||
char hexgrip[40+4+1];
|
||||
|
||||
for (i=0; i < 20; i++)
|
||||
sprintf (hexgrip+2*i, "%02X", grip[i]);
|
||||
strcpy (hexgrip+40, ".key");
|
||||
|
||||
fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
|
||||
if (force)
|
||||
fp = fopen (fname, "wb");
|
||||
else
|
||||
{
|
||||
int fd;
|
||||
|
||||
if (!access (fname, F_OK))
|
||||
{
|
||||
log_error ("secret key file `%s' already exists\n", fname);
|
||||
xfree (fname);
|
||||
return seterr (General_Error);
|
||||
}
|
||||
|
||||
/* We would like to create FNAME but only if it does not already
|
||||
exist. We cannot make this guarantee just using POSIX (GNU
|
||||
provides the "x" opentype for fopen, however, this is not
|
||||
portable). Thus, we use the more flexible open function and
|
||||
then use fdopen to obtain a stream.
|
||||
|
||||
The mode parameter to open is what fopen uses. It will be
|
||||
combined with the process' umask automatically. */
|
||||
fd = open (fname, O_CREAT | O_EXCL | O_RDWR,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||
if (fd < 0)
|
||||
fp = 0;
|
||||
else
|
||||
{
|
||||
fp = fdopen (fd, "wb");
|
||||
if (! fp)
|
||||
close (fd);
|
||||
}
|
||||
}
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
log_error ("can't create `%s': %s\n", fname, strerror (errno));
|
||||
xfree (fname);
|
||||
return seterr (File_Create_Error);
|
||||
}
|
||||
|
||||
if (fwrite (buffer, length, 1, fp) != 1)
|
||||
{
|
||||
log_error ("error writing `%s': %s\n", fname, strerror (errno));
|
||||
fclose (fp);
|
||||
remove (fname);
|
||||
xfree (fname);
|
||||
return seterr (File_Create_Error);
|
||||
}
|
||||
if ( fclose (fp) )
|
||||
{
|
||||
log_error ("error closing `%s': %s\n", fname, strerror (errno));
|
||||
remove (fname);
|
||||
xfree (fname);
|
||||
return seterr (File_Create_Error);
|
||||
}
|
||||
|
||||
xfree (fname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Callback function to try the unprotection from the passpharse query
|
||||
code. */
|
||||
static int
|
||||
try_unprotect_cb (struct pin_entry_info_s *pi)
|
||||
{
|
||||
struct try_unprotect_arg_s *arg = pi->check_cb_arg;
|
||||
size_t dummy;
|
||||
|
||||
assert (!arg->unprotected_key);
|
||||
return agent_unprotect (arg->protected_key, pi->pin,
|
||||
&arg->unprotected_key, &dummy);
|
||||
}
|
||||
|
||||
|
||||
/* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP
|
||||
should be the hex encoded keygrip of that key to be used with the
|
||||
cahing mechanism. */
|
||||
static int
|
||||
unprotect (unsigned char **keybuf, const unsigned char *grip, int ignore_cache)
|
||||
{
|
||||
struct pin_entry_info_s *pi;
|
||||
struct try_unprotect_arg_s arg;
|
||||
int rc, i;
|
||||
unsigned char *result;
|
||||
size_t resultlen;
|
||||
char hexgrip[40+1];
|
||||
|
||||
for (i=0; i < 20; i++)
|
||||
sprintf (hexgrip+2*i, "%02X", grip[i]);
|
||||
hexgrip[40] = 0;
|
||||
|
||||
/* first try to get it from the cache - if there is none or we can't
|
||||
unprotect it, we fall back to ask the user */
|
||||
if (!ignore_cache)
|
||||
{
|
||||
void *cache_marker;
|
||||
const char *pw = agent_get_cache (hexgrip, &cache_marker);
|
||||
if (pw)
|
||||
{
|
||||
rc = agent_unprotect (*keybuf, pw, &result, &resultlen);
|
||||
agent_unlock_cache_entry (&cache_marker);
|
||||
if (!rc)
|
||||
{
|
||||
xfree (*keybuf);
|
||||
*keybuf = result;
|
||||
return 0;
|
||||
}
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pi = gcry_calloc_secure (1, sizeof (*pi) + 100);
|
||||
pi->max_length = 100;
|
||||
pi->min_digits = 0; /* we want a real passphrase */
|
||||
pi->max_digits = 8;
|
||||
pi->max_tries = 3;
|
||||
pi->check_cb = try_unprotect_cb;
|
||||
arg.protected_key = *keybuf;
|
||||
arg.unprotected_key = NULL;
|
||||
pi->check_cb_arg = &arg;
|
||||
|
||||
rc = agent_askpin (NULL, pi);
|
||||
if (!rc)
|
||||
{
|
||||
assert (arg.unprotected_key);
|
||||
agent_put_cache (hexgrip, pi->pin, 0);
|
||||
xfree (*keybuf);
|
||||
*keybuf = arg.unprotected_key;
|
||||
}
|
||||
xfree (pi);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Return the secret key as an S-Exp after locating it using the grip.
|
||||
Returns NULL if key is not available or the operation should be
|
||||
diverted to a token. In the latter case shadow_info will point to
|
||||
an allocated S-Expression with the shadow_info part from the file.
|
||||
With IGNORE_CACHE passed as true the passphrase is not taken from
|
||||
the cache.*/
|
||||
GCRY_SEXP
|
||||
agent_key_from_file (const unsigned char *grip, unsigned char **shadow_info,
|
||||
int ignore_cache)
|
||||
{
|
||||
int i, rc;
|
||||
char *fname;
|
||||
FILE *fp;
|
||||
struct stat st;
|
||||
unsigned char *buf;
|
||||
size_t len, buflen, erroff;
|
||||
GCRY_SEXP s_skey;
|
||||
char hexgrip[40+4+1];
|
||||
|
||||
if (shadow_info)
|
||||
*shadow_info = NULL;
|
||||
|
||||
for (i=0; i < 20; i++)
|
||||
sprintf (hexgrip+2*i, "%02X", grip[i]);
|
||||
strcpy (hexgrip+40, ".key");
|
||||
|
||||
fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
|
||||
fp = fopen (fname, "rb");
|
||||
if (!fp)
|
||||
{
|
||||
log_error ("can't open `%s': %s\n", fname, strerror (errno));
|
||||
xfree (fname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fstat (fileno(fp), &st))
|
||||
{
|
||||
log_error ("can't stat `%s': %s\n", fname, strerror (errno));
|
||||
xfree (fname);
|
||||
fclose (fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buflen = st.st_size;
|
||||
buf = xmalloc (buflen+1);
|
||||
if (fread (buf, buflen, 1, fp) != 1)
|
||||
{
|
||||
log_error ("error reading `%s': %s\n", fname, strerror (errno));
|
||||
xfree (fname);
|
||||
fclose (fp);
|
||||
xfree (buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = gcry_sexp_sscan (&s_skey, &erroff, buf, buflen);
|
||||
xfree (fname);
|
||||
fclose (fp);
|
||||
xfree (buf);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("failed to build S-Exp (off=%u): %s\n",
|
||||
(unsigned int)erroff, gcry_strerror (rc));
|
||||
return NULL;
|
||||
}
|
||||
len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||
assert (len);
|
||||
buf = xtrymalloc (len);
|
||||
if (!buf)
|
||||
{
|
||||
gcry_sexp_release (s_skey);
|
||||
return NULL;
|
||||
}
|
||||
len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, buf, len);
|
||||
assert (len);
|
||||
gcry_sexp_release (s_skey);
|
||||
|
||||
switch (agent_private_key_type (buf))
|
||||
{
|
||||
case PRIVATE_KEY_CLEAR:
|
||||
break; /* no unprotection needed */
|
||||
case PRIVATE_KEY_PROTECTED:
|
||||
rc = unprotect (&buf, grip, ignore_cache);
|
||||
if (rc)
|
||||
log_error ("failed to unprotect the secret key: %s\n",
|
||||
gnupg_strerror (rc));
|
||||
break;
|
||||
case PRIVATE_KEY_SHADOWED:
|
||||
if (shadow_info)
|
||||
{
|
||||
const unsigned char *s;
|
||||
size_t n;
|
||||
|
||||
rc = agent_get_shadow_info (buf, &s);
|
||||
if (!rc)
|
||||
{
|
||||
n = gcry_sexp_canon_len (s, 0, NULL,NULL);
|
||||
assert (n);
|
||||
*shadow_info = xtrymalloc (n);
|
||||
if (!*shadow_info)
|
||||
rc = GNUPG_Out_Of_Core;
|
||||
else
|
||||
{
|
||||
memcpy (*shadow_info, s, n);
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
if (rc)
|
||||
log_error ("get_shadow_info failed: %s\n", gnupg_strerror (rc));
|
||||
}
|
||||
rc = -1; /* ugly interface: we return an error but keep a value
|
||||
in shadow_info. */
|
||||
break;
|
||||
default:
|
||||
log_error ("invalid private key format\n");
|
||||
rc = GNUPG_Bad_Secret_Key;
|
||||
break;
|
||||
}
|
||||
if (rc)
|
||||
{
|
||||
xfree (buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* arggg FIXME: does scan support secure memory? */
|
||||
rc = gcry_sexp_sscan (&s_skey, &erroff,
|
||||
buf, gcry_sexp_canon_len (buf, 0, NULL, NULL));
|
||||
xfree (buf);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("failed to build S-Exp (off=%u): %s\n",
|
||||
(unsigned int)erroff, gcry_strerror (rc));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return s_skey;
|
||||
}
|
||||
|
||||
/* Return the secret key as an S-Exp after locating it using the grip.
|
||||
Returns NULL if key is not available. 0 = key is available */
|
||||
int
|
||||
agent_key_available (const unsigned char *grip)
|
||||
{
|
||||
int i;
|
||||
char *fname;
|
||||
char hexgrip[40+4+1];
|
||||
|
||||
for (i=0; i < 20; i++)
|
||||
sprintf (hexgrip+2*i, "%02X", grip[i]);
|
||||
strcpy (hexgrip+40, ".key");
|
||||
|
||||
fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
|
||||
i = !access (fname, R_OK)? 0 : -1;
|
||||
xfree (fname);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
|
200
agent/genkey.c
200
agent/genkey.c
@ -1,200 +0,0 @@
|
||||
/* pksign.c - Generate a keypair
|
||||
* Copyright (C) 2002 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 <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "agent.h"
|
||||
#include "i18n.h"
|
||||
|
||||
static int
|
||||
store_key (GCRY_SEXP private, const char *passphrase)
|
||||
{
|
||||
int rc;
|
||||
char *buf;
|
||||
size_t len;
|
||||
unsigned char grip[20];
|
||||
|
||||
if ( !gcry_pk_get_keygrip (private, grip) )
|
||||
{
|
||||
log_error ("can't calculate keygrip\n");
|
||||
return seterr (General_Error);
|
||||
}
|
||||
|
||||
len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||
assert (len);
|
||||
buf = gcry_malloc_secure (len);
|
||||
if (!buf)
|
||||
return seterr (Out_Of_Core);
|
||||
len = gcry_sexp_sprint (private, GCRYSEXP_FMT_CANON, buf, len);
|
||||
assert (len);
|
||||
|
||||
if (passphrase)
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
rc = agent_protect (buf, passphrase, &p, &len);
|
||||
if (rc)
|
||||
{
|
||||
xfree (buf);
|
||||
return rc;
|
||||
}
|
||||
xfree (buf);
|
||||
buf = p;
|
||||
}
|
||||
|
||||
rc = agent_write_private_key (grip, buf, len, 0);
|
||||
xfree (buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Callback function to compare the first entered PIN with the one
|
||||
currently beeing entered. */
|
||||
static int
|
||||
reenter_compare_cb (struct pin_entry_info_s *pi)
|
||||
{
|
||||
const char *pin1 = pi->check_cb_arg;
|
||||
|
||||
if (!strcmp (pin1, pi->pin))
|
||||
return 0; /* okay */
|
||||
pi->cb_errtext = _("does not match - try again");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Generate a new keypair according to the parameters given in
|
||||
KEYPARAM */
|
||||
int
|
||||
agent_genkey (CTRL ctrl, const char *keyparam, size_t keyparamlen,
|
||||
FILE *outfp)
|
||||
{
|
||||
GCRY_SEXP s_keyparam, s_key, s_private, s_public;
|
||||
struct pin_entry_info_s *pi, *pi2;
|
||||
int rc;
|
||||
size_t len;
|
||||
char *buf;
|
||||
|
||||
rc = gcry_sexp_sscan (&s_keyparam, NULL, keyparam, keyparamlen);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("failed to convert keyparam: %s\n", gcry_strerror (rc));
|
||||
return seterr (Invalid_Data);
|
||||
}
|
||||
|
||||
/* Get the passphrase now, cause key generation may take a while. */
|
||||
{
|
||||
const char *text1 = _("Please enter the passphrase to%0A"
|
||||
"to protect your new key");
|
||||
const char *text2 = _("Please re-enter this passphrase");
|
||||
|
||||
pi = gcry_calloc_secure (2, sizeof (*pi) + 100);
|
||||
pi2 = pi + (sizeof *pi + 100);
|
||||
pi->max_length = 100;
|
||||
pi->max_tries = 3;
|
||||
pi2->max_length = 100;
|
||||
pi2->max_tries = 3;
|
||||
pi2->check_cb = reenter_compare_cb;
|
||||
pi2->check_cb_arg = pi->pin;
|
||||
|
||||
rc = agent_askpin (text1, pi);
|
||||
if (!rc)
|
||||
rc = agent_askpin (text2, pi2);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (!*pi->pin)
|
||||
{
|
||||
xfree (pi);
|
||||
pi = NULL; /* User does not want a passphrase. */
|
||||
}
|
||||
}
|
||||
|
||||
rc = gcry_pk_genkey (&s_key, s_keyparam );
|
||||
gcry_sexp_release (s_keyparam);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("key generation failed: %s\n", gcry_strerror (rc));
|
||||
xfree (pi);
|
||||
return map_gcry_err (rc);
|
||||
}
|
||||
|
||||
/* break out the parts */
|
||||
s_private = gcry_sexp_find_token (s_key, "private-key", 0);
|
||||
if (!s_private)
|
||||
{
|
||||
log_error ("key generation failed: invalid return value\n");
|
||||
gcry_sexp_release (s_key);
|
||||
xfree (pi);
|
||||
return seterr (Invalid_Data);
|
||||
}
|
||||
s_public = gcry_sexp_find_token (s_key, "public-key", 0);
|
||||
if (!s_public)
|
||||
{
|
||||
log_error ("key generation failed: invalid return value\n");
|
||||
gcry_sexp_release (s_private);
|
||||
gcry_sexp_release (s_key);
|
||||
xfree (pi);
|
||||
return seterr (Invalid_Data);
|
||||
}
|
||||
gcry_sexp_release (s_key); s_key = NULL;
|
||||
|
||||
/* store the secret key */
|
||||
log_debug ("storing private key\n");
|
||||
rc = store_key (s_private, pi? pi->pin:NULL);
|
||||
xfree (pi); pi = NULL;
|
||||
gcry_sexp_release (s_private);
|
||||
if (rc)
|
||||
{
|
||||
gcry_sexp_release (s_public);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* return the public key */
|
||||
log_debug ("returning public key\n");
|
||||
len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||
assert (len);
|
||||
buf = xmalloc (len);
|
||||
if (!buf)
|
||||
{
|
||||
gcry_sexp_release (s_private);
|
||||
gcry_sexp_release (s_public);
|
||||
return seterr (Out_Of_Core);
|
||||
}
|
||||
len = gcry_sexp_sprint (s_public, GCRYSEXP_FMT_CANON, buf, len);
|
||||
assert (len);
|
||||
if (fwrite (buf, len, 1, outfp) != 1)
|
||||
{
|
||||
log_error ("error writing public key: %s\n", strerror (errno));
|
||||
gcry_sexp_release (s_private);
|
||||
gcry_sexp_release (s_public);
|
||||
xfree (buf);
|
||||
return seterr (File_Create_Error);
|
||||
}
|
||||
gcry_sexp_release (s_public);
|
||||
xfree (buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,916 +0,0 @@
|
||||
/* gpg-agent.c - The GnuPG Agent
|
||||
* Copyright (C) 2000, 2001, 2002 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 <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#ifdef USE_GNU_PTH
|
||||
# include <pth.h>
|
||||
#endif
|
||||
|
||||
#include <gcrypt.h>
|
||||
|
||||
#define JNLIB_NEED_LOG_LOGV
|
||||
#include "agent.h"
|
||||
#include "../assuan/assuan.h" /* malloc hooks */
|
||||
|
||||
#include "i18n.h"
|
||||
#include "sysutils.h"
|
||||
|
||||
|
||||
enum cmd_and_opt_values
|
||||
{ aNull = 0,
|
||||
oCsh = 'c',
|
||||
oQuiet = 'q',
|
||||
oSh = 's',
|
||||
oVerbose = 'v',
|
||||
|
||||
oNoVerbose = 500,
|
||||
oOptions,
|
||||
oDebug,
|
||||
oDebugAll,
|
||||
oDebugWait,
|
||||
oNoGreeting,
|
||||
oNoOptions,
|
||||
oHomedir,
|
||||
oNoDetach,
|
||||
oNoGrab,
|
||||
oLogFile,
|
||||
oServer,
|
||||
oDaemon,
|
||||
oBatch,
|
||||
|
||||
oPinentryProgram,
|
||||
oDisplay,
|
||||
oTTYname,
|
||||
oTTYtype,
|
||||
oLCctype,
|
||||
oLCmessages,
|
||||
oScdaemonProgram,
|
||||
oDefCacheTTL,
|
||||
oDisablePth,
|
||||
|
||||
oIgnoreCacheForSigning,
|
||||
oKeepTTY,
|
||||
oKeepDISPLAY,
|
||||
|
||||
aTest };
|
||||
|
||||
|
||||
|
||||
static ARGPARSE_OPTS opts[] = {
|
||||
|
||||
{ 301, NULL, 0, N_("@Options:\n ") },
|
||||
|
||||
{ oServer, "server", 0, N_("run in server mode (foreground)") },
|
||||
{ oDaemon, "daemon", 0, N_("run in daemon mode (background)") },
|
||||
{ oVerbose, "verbose", 0, N_("verbose") },
|
||||
{ oQuiet, "quiet", 0, N_("be somewhat more quiet") },
|
||||
{ oSh, "sh", 0, N_("sh-style command output") },
|
||||
{ oCsh, "csh", 0, N_("csh-style command output") },
|
||||
{ oOptions, "options" , 2, N_("read options from file")},
|
||||
{ oDebug, "debug" ,4|16, N_("set debugging flags")},
|
||||
{ oDebugAll, "debug-all" ,0, N_("enable full debugging")},
|
||||
{ oDebugWait,"debug-wait",1, "@"},
|
||||
{ oNoDetach, "no-detach" ,0, N_("do not detach from the console")},
|
||||
{ oNoGrab, "no-grab" ,0, N_("do not grab keyboard and mouse")},
|
||||
{ oLogFile, "log-file" ,2, N_("use a log file for the server")},
|
||||
{ oDisablePth, "disable-pth", 0, N_("do not allow multiple connections")},
|
||||
|
||||
{ oPinentryProgram, "pinentry-program", 2 , "path to PIN Entry program" },
|
||||
{ oDisplay, "display", 2, "set the display" },
|
||||
{ oTTYname, "ttyname", 2, "set the tty terminal node name" },
|
||||
{ oTTYtype, "ttytype", 2, "set the tty terminal type" },
|
||||
{ oLCctype, "lc-ctype", 2, "set the tty LC_CTYPE value" },
|
||||
{ oLCmessages, "lc-messages", 2, "set the tty LC_MESSAGES value" },
|
||||
|
||||
{ oScdaemonProgram, "scdaemon-program", 2 , "path to SCdaemon program" },
|
||||
{ oDefCacheTTL, "default-cache-ttl", 4,
|
||||
"|N|expire cached PINs after N seconds"},
|
||||
{ oIgnoreCacheForSigning, "ignore-cache-for-signing", 0,
|
||||
"do not use the PIN cache when signing"},
|
||||
{ oKeepTTY, "keep-tty", 0, N_("ignore requests to change the TTY")},
|
||||
{ oKeepDISPLAY, "keep-display",
|
||||
0, N_("ignore requests to change the X display")},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
||||
static volatile int caught_fatal_sig = 0;
|
||||
|
||||
/* flag to indicate that a shutdown was requested */
|
||||
static int shutdown_pending;
|
||||
|
||||
|
||||
/* It is possible that we are currently running under setuid permissions */
|
||||
static int maybe_setuid = 1;
|
||||
|
||||
/* Name of the communication socket */
|
||||
static char socket_name[128];
|
||||
|
||||
static void create_directories (void);
|
||||
#ifdef USE_GNU_PTH
|
||||
static void handle_connections (int listen_fd);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static const char *
|
||||
my_strusage (int level)
|
||||
{
|
||||
const char *p;
|
||||
switch (level)
|
||||
{
|
||||
case 11: p = "gpg-agent (GnuPG)";
|
||||
break;
|
||||
case 13: p = VERSION; break;
|
||||
case 17: p = PRINTABLE_OS_NAME; break;
|
||||
case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
|
||||
break;
|
||||
case 1:
|
||||
case 40: p = _("Usage: gpg-agent [options] (-h for help)");
|
||||
break;
|
||||
case 41: p = _("Syntax: gpg-agent [options] [command [args]]\n"
|
||||
"Secret key management for GnuPG\n");
|
||||
break;
|
||||
|
||||
default: p = NULL;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
i18n_init (void)
|
||||
{
|
||||
#ifdef USE_SIMPLE_GETTEXT
|
||||
set_gettext_file( PACKAGE );
|
||||
#else
|
||||
#ifdef ENABLE_NLS
|
||||
setlocale (LC_ALL, "");
|
||||
bindtextdomain (PACKAGE, LOCALEDIR);
|
||||
textdomain (PACKAGE);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Used by gcry for logging */
|
||||
static void
|
||||
my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
|
||||
{
|
||||
/* translate the log levels */
|
||||
switch (level)
|
||||
{
|
||||
case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
|
||||
case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
|
||||
case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
|
||||
case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
|
||||
case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
|
||||
case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break;
|
||||
case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
|
||||
default: level = JNLIB_LOG_ERROR; break;
|
||||
}
|
||||
log_logv (level, fmt, arg_ptr);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cleanup (void)
|
||||
{
|
||||
if (*socket_name)
|
||||
{
|
||||
char *p;
|
||||
|
||||
remove (socket_name);
|
||||
p = strrchr (socket_name, '/');
|
||||
if (p)
|
||||
{
|
||||
*p = 0;
|
||||
rmdir (socket_name);
|
||||
*p = '/';
|
||||
}
|
||||
*socket_name = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static RETSIGTYPE
|
||||
cleanup_sh (int sig)
|
||||
{
|
||||
if (caught_fatal_sig)
|
||||
raise (sig);
|
||||
caught_fatal_sig = 1;
|
||||
|
||||
/* gcry_control( GCRYCTL_TERM_SECMEM );*/
|
||||
cleanup ();
|
||||
|
||||
#ifndef HAVE_DOSISH_SYSTEM
|
||||
{ /* reset action to default action and raise signal again */
|
||||
struct sigaction nact;
|
||||
nact.sa_handler = SIG_DFL;
|
||||
sigemptyset( &nact.sa_mask );
|
||||
nact.sa_flags = 0;
|
||||
sigaction( sig, &nact, NULL);
|
||||
}
|
||||
#endif
|
||||
raise( sig );
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv )
|
||||
{
|
||||
ARGPARSE_ARGS pargs;
|
||||
int orig_argc;
|
||||
int may_coredump;
|
||||
char **orig_argv;
|
||||
FILE *configfp = NULL;
|
||||
char *configname = NULL;
|
||||
const char *shell;
|
||||
unsigned configlineno;
|
||||
int parse_debug = 0;
|
||||
int default_config =1;
|
||||
int greeting = 0;
|
||||
int nogreeting = 0;
|
||||
int pipe_server = 0;
|
||||
int is_daemon = 0;
|
||||
int nodetach = 0;
|
||||
int csh_style = 0;
|
||||
char *logfile = NULL;
|
||||
int debug_wait = 0;
|
||||
int disable_pth = 0;
|
||||
|
||||
set_strusage (my_strusage);
|
||||
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
|
||||
/* Please note that we may running SUID(ROOT), so be very CAREFUL
|
||||
when adding any stuff between here and the call to INIT_SECMEM()
|
||||
somewhere after the option parsing */
|
||||
log_set_prefix ("gpg-agent", 1|4);
|
||||
i18n_init ();
|
||||
|
||||
/* check that the libraries are suitable. Do it here because
|
||||
the option parsing may need services of the library */
|
||||
if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
|
||||
{
|
||||
log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
|
||||
NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
|
||||
}
|
||||
|
||||
assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
|
||||
#ifdef USE_GNU_PTH
|
||||
assuan_set_io_func (pth_read, pth_write);
|
||||
#endif
|
||||
|
||||
gcry_set_log_handler (my_gcry_logger, NULL);
|
||||
gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
|
||||
|
||||
may_coredump = disable_core_dumps ();
|
||||
|
||||
shell = getenv ("SHELL");
|
||||
if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
|
||||
csh_style = 1;
|
||||
|
||||
opt.homedir = getenv("GNUPGHOME");
|
||||
if (!opt.homedir || !*opt.homedir)
|
||||
opt.homedir = GNUPG_DEFAULT_HOMEDIR;
|
||||
opt.def_cache_ttl = 10*60; /* default to 10 minutes */
|
||||
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* initialize the secure memory. */
|
||||
gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
|
||||
maybe_setuid = 0;
|
||||
|
||||
/*
|
||||
Now we are now working under our real uid
|
||||
*/
|
||||
|
||||
|
||||
if (default_config)
|
||||
configname = make_filename (opt.homedir, "gpg-agent.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) );
|
||||
exit(2);
|
||||
}
|
||||
xfree (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 oQuiet: opt.quiet = 1; break;
|
||||
case oVerbose: opt.verbose++; break;
|
||||
case oBatch: opt.batch=1; break;
|
||||
|
||||
case oDebug: opt.debug |= pargs.r.ret_ulong; break;
|
||||
case oDebugAll: opt.debug = ~0; break;
|
||||
case oDebugWait: debug_wait = pargs.r.ret_int; break;
|
||||
|
||||
case oOptions:
|
||||
/* config files may not be nested (silently ignore them) */
|
||||
if (!configfp)
|
||||
{
|
||||
xfree(configname);
|
||||
configname = xstrdup(pargs.r.ret_str);
|
||||
goto next_pass;
|
||||
}
|
||||
break;
|
||||
case oNoGreeting: nogreeting = 1; break;
|
||||
case oNoVerbose: opt.verbose = 0; break;
|
||||
case oNoOptions: break; /* no-options */
|
||||
case oHomedir: opt.homedir = pargs.r.ret_str; break;
|
||||
case oNoDetach: nodetach = 1; break;
|
||||
case oNoGrab: opt.no_grab = 1; break;
|
||||
case oLogFile: logfile = pargs.r.ret_str; break;
|
||||
case oCsh: csh_style = 1; break;
|
||||
case oSh: csh_style = 0; break;
|
||||
case oServer: pipe_server = 1; break;
|
||||
case oDaemon: is_daemon = 1; break;
|
||||
case oDisablePth: disable_pth = 1; break;
|
||||
|
||||
case oPinentryProgram: opt.pinentry_program = pargs.r.ret_str; break;
|
||||
case oDisplay: opt.display = xstrdup (pargs.r.ret_str); break;
|
||||
case oTTYname: opt.ttyname = xstrdup (pargs.r.ret_str); break;
|
||||
case oTTYtype: opt.ttytype = xstrdup (pargs.r.ret_str); break;
|
||||
case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break;
|
||||
case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break;
|
||||
case oScdaemonProgram: opt.scdaemon_program = pargs.r.ret_str; break;
|
||||
case oDefCacheTTL: opt.def_cache_ttl = pargs.r.ret_ulong; break;
|
||||
|
||||
case oIgnoreCacheForSigning: opt.ignore_cache_for_signing = 1; break;
|
||||
case oKeepTTY: opt.keep_tty = 1; break;
|
||||
case oKeepDISPLAY: opt.keep_display = 1; break;
|
||||
|
||||
default : pargs.err = configfp? 1:2; break;
|
||||
}
|
||||
}
|
||||
if (configfp)
|
||||
{
|
||||
fclose( configfp );
|
||||
configfp = NULL;
|
||||
xfree(configname);
|
||||
configname = NULL;
|
||||
goto next_pass;
|
||||
}
|
||||
xfree (configname);
|
||||
configname = NULL;
|
||||
if (log_get_errorcount(0))
|
||||
exit(2);
|
||||
if (nogreeting )
|
||||
greeting = 0;
|
||||
|
||||
if (greeting)
|
||||
{
|
||||
fprintf (stderr, "%s %s; %s\n",
|
||||
strusage(11), strusage(13), strusage(14) );
|
||||
fprintf (stderr, "%s\n", strusage(15) );
|
||||
}
|
||||
#ifdef IS_DEVELOPMENT_VERSION
|
||||
log_info ("NOTE: this is a development version!\n");
|
||||
#endif
|
||||
|
||||
|
||||
if (atexit (cleanup))
|
||||
{
|
||||
log_error ("atexit failed\n");
|
||||
cleanup ();
|
||||
exit (1);
|
||||
}
|
||||
|
||||
create_directories ();
|
||||
|
||||
if (debug_wait && pipe_server)
|
||||
{
|
||||
log_debug ("waiting for debugger - my pid is %u .....\n",
|
||||
(unsigned int)getpid());
|
||||
sleep (debug_wait);
|
||||
log_debug ("... okay\n");
|
||||
}
|
||||
|
||||
/* now start with logging to a file if this is desired */
|
||||
if (logfile)
|
||||
{
|
||||
log_set_file (logfile);
|
||||
log_set_prefix (NULL, 1|2|4);
|
||||
}
|
||||
|
||||
|
||||
if (pipe_server)
|
||||
{ /* this is the simple pipe based server */
|
||||
start_command_handler (-1, -1);
|
||||
}
|
||||
else if (!is_daemon)
|
||||
{
|
||||
log_info (_("please use the option `--daemon'"
|
||||
" to run the program in the background\n"));
|
||||
}
|
||||
else
|
||||
{ /* regular server mode */
|
||||
int fd;
|
||||
pid_t pid;
|
||||
int len;
|
||||
struct sockaddr_un serv_addr;
|
||||
char *p;
|
||||
|
||||
*socket_name = 0;
|
||||
snprintf (socket_name, DIM(socket_name)-1,
|
||||
"/tmp/gpg-XXXXXX/S.gpg-agent");
|
||||
socket_name[DIM(socket_name)-1] = 0;
|
||||
p = strrchr (socket_name, '/');
|
||||
if (!p)
|
||||
BUG ();
|
||||
*p = 0;;
|
||||
if (!mkdtemp(socket_name))
|
||||
{
|
||||
log_error ("can't create directory `%s': %s\n",
|
||||
socket_name, strerror(errno) );
|
||||
exit (1);
|
||||
}
|
||||
*p = '/';
|
||||
|
||||
if (strchr (socket_name, ':') )
|
||||
{
|
||||
log_error ("colons are not allowed in the socket name\n");
|
||||
exit (1);
|
||||
}
|
||||
if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path )
|
||||
{
|
||||
log_error ("name of socket too long\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
fd = socket (AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd == -1)
|
||||
{
|
||||
log_error ("can't create socket: %s\n", strerror(errno) );
|
||||
exit (1);
|
||||
}
|
||||
|
||||
memset (&serv_addr, 0, sizeof serv_addr);
|
||||
serv_addr.sun_family = AF_UNIX;
|
||||
strcpy (serv_addr.sun_path, socket_name);
|
||||
len = (offsetof (struct sockaddr_un, sun_path)
|
||||
+ strlen(serv_addr.sun_path) + 1);
|
||||
|
||||
if (bind (fd, (struct sockaddr*)&serv_addr, len) == -1)
|
||||
{
|
||||
log_error ("error binding socket to `%s': %s\n",
|
||||
serv_addr.sun_path, strerror (errno) );
|
||||
close (fd);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (listen (fd, 5 ) == -1)
|
||||
{
|
||||
log_error ("listen() failed: %s\n", strerror (errno));
|
||||
close (fd);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (opt.verbose)
|
||||
log_info ("listening on socket `%s'\n", socket_name );
|
||||
|
||||
|
||||
fflush (NULL);
|
||||
pid = fork ();
|
||||
if (pid == (pid_t)-1)
|
||||
{
|
||||
log_fatal ("fork failed: %s\n", strerror (errno) );
|
||||
exit (1);
|
||||
}
|
||||
else if (pid)
|
||||
{ /* we are the parent */
|
||||
char *infostr;
|
||||
|
||||
close (fd);
|
||||
|
||||
/* create the info string: <name>:<pid>:<protocol_version> */
|
||||
if (asprintf (&infostr, "GPG_AGENT_INFO=%s:%lu:1",
|
||||
socket_name, (ulong)pid ) < 0)
|
||||
{
|
||||
log_error ("out of core\n");
|
||||
kill (pid, SIGTERM);
|
||||
exit (1);
|
||||
}
|
||||
*socket_name = 0; /* don't let cleanup() remove the socket -
|
||||
the child should do this from now on */
|
||||
if (argc)
|
||||
{ /* run the program given on the commandline */
|
||||
if (putenv (infostr))
|
||||
{
|
||||
log_error ("failed to set environment: %s\n",
|
||||
strerror (errno) );
|
||||
kill (pid, SIGTERM );
|
||||
exit (1);
|
||||
}
|
||||
execvp (argv[0], argv);
|
||||
log_error ("failed to run the command: %s\n", strerror (errno));
|
||||
kill (pid, SIGTERM);
|
||||
exit (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* print the environment string, so that the caller can use
|
||||
shell's eval to set it */
|
||||
if (csh_style)
|
||||
{
|
||||
*strchr (infostr, '=') = ' ';
|
||||
printf ( "setenv %s\n", infostr);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ( "%s; export GPG_AGENT_INFO;\n", infostr);
|
||||
}
|
||||
free (infostr);
|
||||
exit (0);
|
||||
}
|
||||
/*NEVER REACHED*/
|
||||
} /* end parent */
|
||||
|
||||
|
||||
/* this is the child */
|
||||
|
||||
/* detach from tty and put process into a new session */
|
||||
if (!nodetach )
|
||||
{
|
||||
int i;
|
||||
|
||||
/* close stdin, stdout and stderr unless it is the log stream */
|
||||
for (i=0; i <= 2; i++)
|
||||
{
|
||||
if ( log_get_fd () != i)
|
||||
close (i);
|
||||
}
|
||||
if (setsid() == -1)
|
||||
{
|
||||
log_error ("setsid() failed: %s\n", strerror(errno) );
|
||||
cleanup ();
|
||||
exit (1);
|
||||
}
|
||||
opt.running_detached = 1;
|
||||
}
|
||||
|
||||
if (chdir("/"))
|
||||
{
|
||||
log_error ("chdir to / failed: %s\n", strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_GNU_PTH
|
||||
if (!disable_pth)
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
if (!pth_init ())
|
||||
{
|
||||
log_error ("failed to initialize the Pth library\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sigemptyset (&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
sigaction (SIGPIPE, &sa, NULL);
|
||||
handle_connections (fd);
|
||||
}
|
||||
else
|
||||
#endif /*!USE_GNU_PTH*/
|
||||
/* setup signals */
|
||||
{
|
||||
struct sigaction oact, nact;
|
||||
|
||||
nact.sa_handler = cleanup_sh;
|
||||
sigemptyset (&nact.sa_mask);
|
||||
nact.sa_flags = 0;
|
||||
|
||||
sigaction (SIGHUP, NULL, &oact);
|
||||
if (oact.sa_handler != SIG_IGN)
|
||||
sigaction (SIGHUP, &nact, NULL);
|
||||
sigaction( SIGTERM, NULL, &oact );
|
||||
if (oact.sa_handler != SIG_IGN)
|
||||
sigaction (SIGTERM, &nact, NULL);
|
||||
nact.sa_handler = SIG_IGN;
|
||||
sigaction (SIGPIPE, &nact, NULL);
|
||||
sigaction (SIGINT, &nact, NULL);
|
||||
|
||||
start_command_handler (fd, -1);
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
agent_exit (int rc)
|
||||
{
|
||||
/*FIXME: update_random_seed_file();*/
|
||||
#if 1
|
||||
/* at this time a bit annoying */
|
||||
if (opt.debug & DBG_MEMSTAT_VALUE)
|
||||
{
|
||||
gcry_control( GCRYCTL_DUMP_MEMORY_STATS );
|
||||
gcry_control( GCRYCTL_DUMP_RANDOM_STATS );
|
||||
}
|
||||
if (opt.debug)
|
||||
gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
|
||||
#endif
|
||||
gcry_control (GCRYCTL_TERM_SECMEM );
|
||||
rc = rc? rc : log_get_errorcount(0)? 2 : 0;
|
||||
exit (rc);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
reread_configuration (void)
|
||||
{
|
||||
/* FIXME: Move parts of the option parsing to here. */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
create_private_keys_directory (const char *home)
|
||||
{
|
||||
char *fname;
|
||||
struct stat statbuf;
|
||||
|
||||
fname = make_filename (home, GNUPG_PRIVATE_KEYS_DIR, NULL);
|
||||
if (stat (fname, &statbuf) && errno == ENOENT)
|
||||
{
|
||||
if (mkdir (fname, S_IRUSR|S_IWUSR|S_IXUSR ))
|
||||
log_error (_("can't create directory `%s': %s\n"),
|
||||
fname, strerror(errno) );
|
||||
else if (!opt.quiet)
|
||||
log_info (_("directory `%s' created\n"), fname);
|
||||
}
|
||||
xfree (fname);
|
||||
}
|
||||
|
||||
/* Create the directory only if the supplied directory name is the
|
||||
same as the default one. This way we avoid to create arbitrary
|
||||
directories when a non-default home directory is used. To cope
|
||||
with HOME, we compare only the suffix if we see that the default
|
||||
homedir does start with a tilde. We don't stop here in case of
|
||||
problems because other functions will throw an error anyway.*/
|
||||
static void
|
||||
create_directories (void)
|
||||
{
|
||||
struct stat statbuf;
|
||||
const char *defhome = GNUPG_DEFAULT_HOMEDIR;
|
||||
char *home;
|
||||
|
||||
home = make_filename (opt.homedir, NULL);
|
||||
if ( stat (home, &statbuf) )
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
{
|
||||
if ( (*defhome == '~'
|
||||
&& (strlen (home) >= strlen (defhome+1)
|
||||
&& !strcmp (home + strlen(home)
|
||||
- strlen (defhome+1), defhome+1)))
|
||||
|| (*defhome != '~' && !strcmp (home, defhome) )
|
||||
)
|
||||
{
|
||||
if (mkdir (home, S_IRUSR|S_IWUSR|S_IXUSR ))
|
||||
log_error (_("can't create directory `%s': %s\n"),
|
||||
home, strerror(errno) );
|
||||
else
|
||||
{
|
||||
if (!opt.quiet)
|
||||
log_info (_("directory `%s' created\n"), home);
|
||||
create_private_keys_directory (home);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
log_error ("error stat-ing `%s': %s\n", home, strerror (errno));
|
||||
}
|
||||
else if ( !S_ISDIR(statbuf.st_mode))
|
||||
{
|
||||
log_error ("can't use `%s' as home directory\n", home);
|
||||
}
|
||||
else /* exists and is a directory. */
|
||||
{
|
||||
create_private_keys_directory (home);
|
||||
}
|
||||
xfree (home);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef USE_GNU_PTH
|
||||
static void
|
||||
handle_signal (int signo)
|
||||
{
|
||||
switch (signo)
|
||||
{
|
||||
case SIGHUP:
|
||||
log_info ("SIGHUP received - "
|
||||
"re-reading configuration and flushing cache\n");
|
||||
agent_flush_cache ();
|
||||
reread_configuration ();
|
||||
break;
|
||||
|
||||
case SIGUSR1:
|
||||
if (opt.verbose < 5)
|
||||
opt.verbose++;
|
||||
log_info ("SIGUSR1 received - verbosity set to %d\n", opt.verbose);
|
||||
break;
|
||||
|
||||
case SIGUSR2:
|
||||
if (opt.verbose)
|
||||
opt.verbose--;
|
||||
log_info ("SIGUSR2 received - verbosity set to %d\n", opt.verbose );
|
||||
break;
|
||||
|
||||
case SIGTERM:
|
||||
if (!shutdown_pending)
|
||||
log_info ("SIGTERM received - shutting down ...\n");
|
||||
else
|
||||
log_info ("SIGTERM received - still %ld running threads\n",
|
||||
pth_ctrl( PTH_CTRL_GETTHREADS ));
|
||||
shutdown_pending++;
|
||||
if (shutdown_pending > 2)
|
||||
{
|
||||
log_info ("shutdown forced\n");
|
||||
log_info ("%s %s stopped\n", strusage(11), strusage(13) );
|
||||
cleanup ();
|
||||
agent_exit (0);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIGINT:
|
||||
log_info ("SIGINT received - immediate shutdown\n");
|
||||
log_info( "%s %s stopped\n", strusage(11), strusage(13));
|
||||
cleanup ();
|
||||
agent_exit (0);
|
||||
break;
|
||||
|
||||
default:
|
||||
log_info ("signal %d received - no action defined\n", signo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
start_connection_thread (void *arg)
|
||||
{
|
||||
int fd = (int)arg;
|
||||
|
||||
if (opt.verbose)
|
||||
log_info ("handler for fd %d started\n", fd);
|
||||
start_command_handler (-1, fd);
|
||||
if (opt.verbose)
|
||||
log_info ("handler for fd %d terminated\n", fd);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handle_connections (int listen_fd)
|
||||
{
|
||||
pth_attr_t tattr;
|
||||
pth_event_t ev;
|
||||
sigset_t sigs;
|
||||
int signo;
|
||||
struct sockaddr_un paddr;
|
||||
socklen_t plen = sizeof( paddr );
|
||||
int fd;
|
||||
|
||||
tattr = pth_attr_new();
|
||||
pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
|
||||
pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 32*1024);
|
||||
pth_attr_set (tattr, PTH_ATTR_NAME, "gpg-agent");
|
||||
|
||||
sigemptyset (&sigs );
|
||||
sigaddset (&sigs, SIGHUP);
|
||||
sigaddset (&sigs, SIGUSR1);
|
||||
sigaddset (&sigs, SIGUSR2);
|
||||
sigaddset (&sigs, SIGINT);
|
||||
sigaddset (&sigs, SIGTERM);
|
||||
ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (shutdown_pending)
|
||||
{
|
||||
if (pth_ctrl (PTH_CTRL_GETTHREADS) == 1)
|
||||
break; /* ready */
|
||||
|
||||
/* Do not accept anymore connections and wait for existing
|
||||
connections to terminate */
|
||||
signo = 0;
|
||||
pth_wait (ev);
|
||||
if (pth_event_occurred (ev) && signo)
|
||||
handle_signal (signo);
|
||||
continue;
|
||||
}
|
||||
|
||||
fd = pth_accept_ev (listen_fd, (struct sockaddr *)&paddr, &plen, ev);
|
||||
if (fd == -1)
|
||||
{
|
||||
if (pth_event_occurred (ev))
|
||||
{
|
||||
handle_signal (signo);
|
||||
continue;
|
||||
}
|
||||
log_error ("accept failed: %s - waiting 1s\n", strerror (errno));
|
||||
pth_sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!pth_spawn (tattr, start_connection_thread, (void*)fd))
|
||||
{
|
||||
log_error ("error spawning connection handler: %s\n",
|
||||
strerror (errno) );
|
||||
close (fd);
|
||||
}
|
||||
}
|
||||
|
||||
pth_event_free (ev, PTH_FREE_ALL);
|
||||
cleanup ();
|
||||
log_info ("%s %s stopped\n", strusage(11), strusage(13));
|
||||
}
|
||||
#endif /*USE_GNU_PTH*/
|
@ -1,380 +0,0 @@
|
||||
/* learncard.c - Handle the LEARN command
|
||||
* Copyright (C) 2002 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 <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "agent.h"
|
||||
#include "../assuan/assuan.h"
|
||||
|
||||
struct keypair_info_s {
|
||||
struct keypair_info_s *next;
|
||||
int no_cert;
|
||||
char *id; /* points into grip */
|
||||
char hexgrip[1];
|
||||
};
|
||||
typedef struct keypair_info_s *KEYPAIR_INFO;
|
||||
|
||||
struct kpinfo_cb_parm_s {
|
||||
int error;
|
||||
KEYPAIR_INFO info;
|
||||
};
|
||||
|
||||
|
||||
struct certinfo_s {
|
||||
struct certinfo_s *next;
|
||||
int type;
|
||||
int done;
|
||||
char id[1];
|
||||
};
|
||||
typedef struct certinfo_s *CERTINFO;
|
||||
|
||||
struct certinfo_cb_parm_s {
|
||||
int error;
|
||||
CERTINFO info;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
release_keypair_info (KEYPAIR_INFO info)
|
||||
{
|
||||
while (info)
|
||||
{
|
||||
KEYPAIR_INFO tmp = info->next;
|
||||
xfree (info);
|
||||
info = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
release_certinfo (CERTINFO info)
|
||||
{
|
||||
while (info)
|
||||
{
|
||||
CERTINFO tmp = info->next;
|
||||
xfree (info);
|
||||
info = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* This callback is used by agent_card_leanr and passed the content of
|
||||
all KEYPAIRINFO lines. It merely stores this data away */
|
||||
static void
|
||||
kpinfo_cb (void *opaque, const char *line)
|
||||
{
|
||||
struct kpinfo_cb_parm_s *parm = opaque;
|
||||
KEYPAIR_INFO item;
|
||||
char *p;
|
||||
|
||||
if (parm->error)
|
||||
return; /* no need to gather data after an error coccured */
|
||||
item = xtrycalloc (1, sizeof *item + strlen (line));
|
||||
if (!item)
|
||||
{
|
||||
parm->error = GNUPG_Out_Of_Core;
|
||||
return;
|
||||
}
|
||||
strcpy (item->hexgrip, line);
|
||||
for (p = item->hexgrip; hexdigitp (p); p++)
|
||||
;
|
||||
if (p == item->hexgrip && *p == 'X' && spacep (p+1))
|
||||
{
|
||||
item->no_cert = 1;
|
||||
p++;
|
||||
}
|
||||
else if ((p - item->hexgrip) != 40 || !spacep (p))
|
||||
{ /* not a 20 byte hex keygrip or not followed by a space */
|
||||
parm->error = GNUPG_Invalid_Response;
|
||||
xfree (item);
|
||||
return;
|
||||
}
|
||||
*p++ = 0;
|
||||
while (spacep (p))
|
||||
p++;
|
||||
item->id = p;
|
||||
while (*p && !spacep (p))
|
||||
p++;
|
||||
if (p == item->id)
|
||||
{ /* invalid ID string */
|
||||
parm->error = GNUPG_Invalid_Response;
|
||||
xfree (item);
|
||||
return;
|
||||
}
|
||||
*p = 0; /* ignore trailing stuff */
|
||||
|
||||
/* store it */
|
||||
item->next = parm->info;
|
||||
parm->info = item;
|
||||
}
|
||||
|
||||
|
||||
/* This callback is used by agent_card_leanr and passed the content of
|
||||
all CERTINFO lines. It merely stores this data away */
|
||||
static void
|
||||
certinfo_cb (void *opaque, const char *line)
|
||||
{
|
||||
struct certinfo_cb_parm_s *parm = opaque;
|
||||
CERTINFO item;
|
||||
int type;
|
||||
char *p, *pend;
|
||||
|
||||
if (parm->error)
|
||||
return; /* no need to gather data after an error coccured */
|
||||
|
||||
type = strtol (line, &p, 10);
|
||||
while (spacep (p))
|
||||
p++;
|
||||
for (pend = p; *pend && !spacep (pend); pend++)
|
||||
;
|
||||
if (p == pend || !*p)
|
||||
{
|
||||
parm->error = GNUPG_Invalid_Response;
|
||||
return;
|
||||
}
|
||||
*pend = 0; /* ignore trailing stuff */
|
||||
|
||||
item = xtrycalloc (1, sizeof *item + strlen (p));
|
||||
if (!item)
|
||||
{
|
||||
parm->error = GNUPG_Out_Of_Core;
|
||||
return;
|
||||
}
|
||||
item->type = type;
|
||||
strcpy (item->id, p);
|
||||
/* store it */
|
||||
item->next = parm->info;
|
||||
parm->info = item;
|
||||
}
|
||||
|
||||
|
||||
/* Create an S-expression with the shadow info. */
|
||||
static unsigned char *
|
||||
make_shadow_info (const char *serialno, const char *idstring)
|
||||
{
|
||||
const char *s;
|
||||
unsigned char *info, *p;
|
||||
char numbuf[21];
|
||||
int n;
|
||||
|
||||
for (s=serialno, n=0; *s && s[1]; s += 2)
|
||||
n++;
|
||||
|
||||
info = p = xtrymalloc (1 + 21 + n
|
||||
+ 21 + strlen (idstring) + 1 + 1);
|
||||
*p++ = '(';
|
||||
sprintf (numbuf, "%d:", n);
|
||||
p = stpcpy (p, numbuf);
|
||||
for (s=serialno; *s && s[1]; s += 2)
|
||||
*p++ = xtoi_2 (s);
|
||||
sprintf (numbuf, "%d:", strlen (idstring));
|
||||
p = stpcpy (p, numbuf);
|
||||
p = stpcpy (p, idstring);
|
||||
*p++ = ')';
|
||||
*p = 0;
|
||||
return info;
|
||||
}
|
||||
|
||||
static int
|
||||
send_cert_back (const char *id, void *assuan_context)
|
||||
{
|
||||
int rc;
|
||||
char *derbuf;
|
||||
size_t derbuflen;
|
||||
|
||||
rc = agent_card_readcert (id, &derbuf, &derbuflen);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("error reading certificate: %s\n",
|
||||
gnupg_strerror (rc));
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = assuan_send_data (assuan_context, derbuf, derbuflen);
|
||||
xfree (derbuf);
|
||||
if (!rc)
|
||||
rc = assuan_send_data (assuan_context, NULL, 0);
|
||||
if (!rc)
|
||||
rc = assuan_write_line (assuan_context, "END");
|
||||
if (rc)
|
||||
{
|
||||
log_error ("sending certificate failed: %s\n",
|
||||
assuan_strerror (rc));
|
||||
return map_assuan_err (rc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Perform the learn operation. If ASSUAN_CONTEXT is not NULL all new
|
||||
certificates are send via Assuan */
|
||||
int
|
||||
agent_handle_learn (void *assuan_context)
|
||||
{
|
||||
int rc;
|
||||
struct kpinfo_cb_parm_s parm;
|
||||
struct certinfo_cb_parm_s cparm;
|
||||
char *serialno = NULL;
|
||||
KEYPAIR_INFO item;
|
||||
unsigned char grip[20];
|
||||
char *p;
|
||||
int i;
|
||||
static int certtype_list[] = {
|
||||
101, /* trusted */
|
||||
102, /* useful */
|
||||
100, /* regular */
|
||||
-1 /* end of list */
|
||||
};
|
||||
|
||||
|
||||
memset (&parm, 0, sizeof parm);
|
||||
memset (&cparm, 0, sizeof cparm);
|
||||
|
||||
/* Check whether a card is present and get the serial number */
|
||||
rc = agent_card_serialno (&serialno);
|
||||
if (rc)
|
||||
goto leave;
|
||||
|
||||
/* now gather all the availabe info */
|
||||
rc = agent_card_learn (kpinfo_cb, &parm, certinfo_cb, &cparm);
|
||||
if (!rc && (parm.error || cparm.error))
|
||||
rc = parm.error? parm.error : cparm.error;
|
||||
if (rc)
|
||||
{
|
||||
log_debug ("agent_card_learn failed: %s\n", gnupg_strerror (rc));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
log_info ("card has S/N: %s\n", serialno);
|
||||
|
||||
/* Write out the certificates in a standard order. */
|
||||
for (i=0; certtype_list[i] != -1; i++)
|
||||
{
|
||||
CERTINFO citem;
|
||||
for (citem = cparm.info; citem; citem = citem->next)
|
||||
{
|
||||
if (certtype_list[i] != citem->type)
|
||||
continue;
|
||||
|
||||
if (opt.verbose)
|
||||
log_info (" id: %s (type=%d)\n",
|
||||
citem->id, citem->type);
|
||||
|
||||
if (assuan_context)
|
||||
{
|
||||
rc = send_cert_back (citem->id, assuan_context);
|
||||
if (rc)
|
||||
goto leave;
|
||||
citem->done = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (item = parm.info; item; item = item->next)
|
||||
{
|
||||
unsigned char *pubkey, *shdkey;
|
||||
size_t n;
|
||||
|
||||
if (opt.verbose)
|
||||
log_info (" id: %s (grip=%s)\n", item->id, item->hexgrip);
|
||||
|
||||
if (item->no_cert)
|
||||
continue; /* no public key yet available */
|
||||
|
||||
for (p=item->hexgrip, i=0; i < 20; p += 2, i++)
|
||||
grip[i] = xtoi_2 (p);
|
||||
|
||||
if (!agent_key_available (grip))
|
||||
continue;
|
||||
|
||||
/* unknown - store it */
|
||||
rc = agent_card_readkey (item->id, &pubkey);
|
||||
if (rc)
|
||||
{
|
||||
log_debug ("agent_card_readkey failed: %s\n", gnupg_strerror (rc));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
{
|
||||
unsigned char *shadow_info = make_shadow_info (serialno, item->id);
|
||||
if (!shadow_info)
|
||||
{
|
||||
rc = GNUPG_Out_Of_Core;
|
||||
xfree (pubkey);
|
||||
goto leave;
|
||||
}
|
||||
rc = agent_shadow_key (pubkey, shadow_info, &shdkey);
|
||||
xfree (shadow_info);
|
||||
}
|
||||
xfree (pubkey);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("shadowing the key failed: %s\n", gnupg_strerror (rc));
|
||||
goto leave;
|
||||
}
|
||||
n = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
|
||||
assert (n);
|
||||
|
||||
rc = agent_write_private_key (grip, shdkey, n, 0);
|
||||
xfree (shdkey);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("error writing key: %s\n", gnupg_strerror (rc));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (opt.verbose)
|
||||
log_info ("stored\n");
|
||||
|
||||
if (assuan_context)
|
||||
{
|
||||
CERTINFO citem;
|
||||
|
||||
/* only send the certificate if we have not done so before */
|
||||
for (citem = cparm.info; citem; citem = citem->next)
|
||||
{
|
||||
if (!strcmp (citem->id, item->id))
|
||||
break;
|
||||
}
|
||||
if (!citem)
|
||||
{
|
||||
rc = send_cert_back (item->id, assuan_context);
|
||||
if (rc)
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
leave:
|
||||
xfree (serialno);
|
||||
release_keypair_info (parm.info);
|
||||
release_certinfo (cparm.info);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
1146
agent/minip12.c
1146
agent/minip12.c
File diff suppressed because it is too large
Load Diff
@ -1,32 +0,0 @@
|
||||
/* minip12.h - Global definitions for the minimal pkcs-12 implementation.
|
||||
* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#ifndef MINIP12_H
|
||||
#define MINIP12_H
|
||||
|
||||
#include <gcrypt.h>
|
||||
|
||||
GcryMPI *p12_parse (const unsigned char *buffer, size_t length,
|
||||
const char *pw);
|
||||
|
||||
unsigned char *p12_build (GcryMPI *kparms, const char *pw, size_t *r_length);
|
||||
|
||||
|
||||
#endif /*MINIP12_H*/
|
@ -1,138 +0,0 @@
|
||||
/* pkdecrypt.c - public key decryption (well, acually using a secret key)
|
||||
* Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "agent.h"
|
||||
|
||||
|
||||
/* DECRYPT the stuff in ciphertext which is expected to be a S-Exp.
|
||||
Try to get the key from CTRL and write the decoded stuff back to
|
||||
OUTFP. */
|
||||
int
|
||||
agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen,
|
||||
FILE *outfp)
|
||||
{
|
||||
GCRY_SEXP s_skey = NULL, s_cipher = NULL, s_plain = NULL;
|
||||
unsigned char *shadow_info = NULL;
|
||||
int rc;
|
||||
char *buf = NULL;
|
||||
size_t len;
|
||||
|
||||
if (!ctrl->have_keygrip)
|
||||
{
|
||||
log_error ("speculative decryption not yet supported\n");
|
||||
rc = seterr (No_Secret_Key);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
rc = gcry_sexp_sscan (&s_cipher, NULL, ciphertext, ciphertextlen);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("failed to convert ciphertext: %s\n", gcry_strerror (rc));
|
||||
rc = seterr (Invalid_Data);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (DBG_CRYPTO)
|
||||
{
|
||||
log_printhex ("keygrip:", ctrl->keygrip, 20);
|
||||
log_printhex ("cipher: ", ciphertext, ciphertextlen);
|
||||
}
|
||||
s_skey = agent_key_from_file (ctrl->keygrip, &shadow_info, 0);
|
||||
if (!s_skey && !shadow_info)
|
||||
{
|
||||
log_error ("failed to read the secret key\n");
|
||||
rc = seterr (No_Secret_Key);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (!s_skey)
|
||||
{ /* divert operation to the smartcard */
|
||||
|
||||
if (!gcry_sexp_canon_len (ciphertext, ciphertextlen, NULL, NULL))
|
||||
{
|
||||
rc = GNUPG_Invalid_Sexp;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
rc = divert_pkdecrypt (ciphertext, shadow_info, &buf, &len );
|
||||
if (rc)
|
||||
{
|
||||
log_error ("smartcard decryption failed: %s\n", gnupg_strerror (rc));
|
||||
goto leave;
|
||||
}
|
||||
/* FIXME: don't use buffering and change the protocol to return
|
||||
a complete S-expression and not just a part. */
|
||||
fprintf (outfp, "%u:", (unsigned int)len);
|
||||
fwrite (buf, 1, len, outfp);
|
||||
putc (0, outfp);
|
||||
}
|
||||
else
|
||||
{ /* no smartcard, but a private key */
|
||||
if (DBG_CRYPTO)
|
||||
{
|
||||
log_debug ("skey: ");
|
||||
gcry_sexp_dump (s_skey);
|
||||
}
|
||||
|
||||
rc = gcry_pk_decrypt (&s_plain, s_cipher, s_skey);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("decryption failed: %s\n", gcry_strerror (rc));
|
||||
rc = map_gcry_err (rc);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (DBG_CRYPTO)
|
||||
{
|
||||
log_debug ("plain: ");
|
||||
gcry_sexp_dump (s_plain);
|
||||
}
|
||||
len = gcry_sexp_sprint (s_plain, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||
assert (len);
|
||||
buf = xmalloc (len);
|
||||
len = gcry_sexp_sprint (s_plain, GCRYSEXP_FMT_CANON, buf, len);
|
||||
assert (len);
|
||||
/* FIXME: we must make sure that no buffering takes place or we are
|
||||
in full control of the buffer memory (easy to do) - should go
|
||||
into assuan. */
|
||||
fwrite (buf, 1, len, outfp);
|
||||
}
|
||||
|
||||
|
||||
leave:
|
||||
gcry_sexp_release (s_skey);
|
||||
gcry_sexp_release (s_plain);
|
||||
gcry_sexp_release (s_cipher);
|
||||
xfree (buf);
|
||||
xfree (shadow_info);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
183
agent/pksign.c
183
agent/pksign.c
@ -1,183 +0,0 @@
|
||||
/* pksign.c - public key signing (well, acually using a secret key)
|
||||
* Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "agent.h"
|
||||
|
||||
|
||||
static int
|
||||
do_encode_md (const unsigned char *digest, size_t digestlen, int algo,
|
||||
unsigned int nbits, GCRY_MPI *r_val)
|
||||
{
|
||||
int nframe = (nbits+7) / 8;
|
||||
byte *frame;
|
||||
int i, n;
|
||||
byte asn[100];
|
||||
size_t asnlen;
|
||||
|
||||
asnlen = DIM(asn);
|
||||
if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
|
||||
{
|
||||
log_error ("no object identifier for algo %d\n", algo);
|
||||
return GNUPG_Internal_Error;
|
||||
}
|
||||
|
||||
if (digestlen + asnlen + 4 > nframe )
|
||||
{
|
||||
log_error ("can't encode a %d bit MD into a %d bits frame\n",
|
||||
(int)(digestlen*8), (int)nbits);
|
||||
return GNUPG_Internal_Error;
|
||||
}
|
||||
|
||||
/* We encode the MD in this way:
|
||||
*
|
||||
* 0 1 PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
|
||||
*
|
||||
* PAD consists of FF bytes.
|
||||
*/
|
||||
frame = xtrymalloc (nframe);
|
||||
if (!frame)
|
||||
return GNUPG_Out_Of_Core;
|
||||
n = 0;
|
||||
frame[n++] = 0;
|
||||
frame[n++] = 1; /* block type */
|
||||
i = nframe - digestlen - 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, digest, digestlen ); n += digestlen;
|
||||
assert ( n == nframe );
|
||||
if (DBG_CRYPTO)
|
||||
log_printhex ("encoded hash:", frame, nframe);
|
||||
|
||||
gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, &nframe);
|
||||
xfree (frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* SIGN whatever information we have accumulated in CTRL and write it
|
||||
back to OUTFP. */
|
||||
int
|
||||
agent_pksign (CTRL ctrl, FILE *outfp, int ignore_cache)
|
||||
{
|
||||
GCRY_SEXP s_skey = NULL, s_hash = NULL, s_sig = NULL;
|
||||
GCRY_MPI frame = NULL;
|
||||
unsigned char *shadow_info = NULL;
|
||||
int rc;
|
||||
char *buf = NULL;
|
||||
size_t len;
|
||||
|
||||
if (!ctrl->have_keygrip)
|
||||
return seterr (No_Secret_Key);
|
||||
|
||||
s_skey = agent_key_from_file (ctrl->keygrip, &shadow_info, ignore_cache);
|
||||
if (!s_skey && !shadow_info)
|
||||
{
|
||||
log_error ("failed to read the secret key\n");
|
||||
rc = seterr (No_Secret_Key);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (!s_skey)
|
||||
{ /* divert operation to the smartcard */
|
||||
unsigned char *sigbuf;
|
||||
|
||||
rc = divert_pksign (ctrl->digest.value,
|
||||
ctrl->digest.valuelen,
|
||||
ctrl->digest.algo,
|
||||
shadow_info, &sigbuf);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("smartcard signing failed: %s\n", gnupg_strerror (rc));
|
||||
goto leave;
|
||||
}
|
||||
len = gcry_sexp_canon_len (sigbuf, 0, NULL, NULL);
|
||||
assert (len);
|
||||
buf = sigbuf;
|
||||
}
|
||||
else
|
||||
{ /* no smartcard, but a private key */
|
||||
|
||||
/* put the hash into a sexp */
|
||||
rc = do_encode_md (ctrl->digest.value,
|
||||
ctrl->digest.valuelen,
|
||||
ctrl->digest.algo,
|
||||
gcry_pk_get_nbits (s_skey),
|
||||
&frame);
|
||||
if (rc)
|
||||
goto leave;
|
||||
if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
|
||||
BUG ();
|
||||
|
||||
if (DBG_CRYPTO)
|
||||
{
|
||||
log_debug ("skey: ");
|
||||
gcry_sexp_dump (s_skey);
|
||||
}
|
||||
|
||||
/* sign */
|
||||
rc = gcry_pk_sign (&s_sig, s_hash, s_skey);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("signing failed: %s\n", gcry_strerror (rc));
|
||||
rc = map_gcry_err (rc);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (DBG_CRYPTO)
|
||||
{
|
||||
log_debug ("result: ");
|
||||
gcry_sexp_dump (s_sig);
|
||||
}
|
||||
|
||||
len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||
assert (len);
|
||||
buf = xmalloc (len);
|
||||
len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, buf, len);
|
||||
assert (len);
|
||||
}
|
||||
|
||||
/* FIXME: we must make sure that no buffering takes place or we are
|
||||
in full control of the buffer memory (easy to do) - should go
|
||||
into assuan. */
|
||||
fwrite (buf, 1, len, outfp);
|
||||
|
||||
leave:
|
||||
gcry_sexp_release (s_skey);
|
||||
gcry_sexp_release (s_hash);
|
||||
gcry_sexp_release (s_sig);
|
||||
gcry_mpi_release (frame);
|
||||
xfree (buf);
|
||||
xfree (shadow_info);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1,977 +0,0 @@
|
||||
/* protect-tool.c - A tool to test the secret key protection
|
||||
* Copyright (C) 2002 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 <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <gcrypt.h>
|
||||
|
||||
#define JNLIB_NEED_LOG_LOGV
|
||||
#include "agent.h"
|
||||
#include "minip12.h"
|
||||
#include "simple-pwquery.h"
|
||||
#include "i18n.h"
|
||||
|
||||
enum cmd_and_opt_values
|
||||
{ aNull = 0,
|
||||
oVerbose = 'v',
|
||||
oArmor = 'a',
|
||||
oPassphrase = 'P',
|
||||
|
||||
oProtect = 'p',
|
||||
oUnprotect = 'u',
|
||||
|
||||
oNoVerbose = 500,
|
||||
oShadow,
|
||||
oShowShadowInfo,
|
||||
oShowKeygrip,
|
||||
|
||||
oP12Import,
|
||||
oP12Export,
|
||||
oStore,
|
||||
oForce,
|
||||
|
||||
aTest };
|
||||
|
||||
struct rsa_secret_key_s
|
||||
{
|
||||
MPI n; /* public modulus */
|
||||
MPI e; /* public exponent */
|
||||
MPI d; /* exponent */
|
||||
MPI p; /* prime p. */
|
||||
MPI q; /* prime q. */
|
||||
MPI u; /* inverse of p mod q. */
|
||||
};
|
||||
|
||||
|
||||
static int opt_armor;
|
||||
static int opt_store;
|
||||
static int opt_force;
|
||||
static const char *passphrase;
|
||||
|
||||
static const char *get_passphrase (void);
|
||||
static int store_private_key (const unsigned char *grip,
|
||||
const void *buffer, size_t length, int force);
|
||||
|
||||
|
||||
static ARGPARSE_OPTS opts[] = {
|
||||
|
||||
{ 301, NULL, 0, N_("@Options:\n ") },
|
||||
|
||||
{ oVerbose, "verbose", 0, "verbose" },
|
||||
{ oArmor, "armor", 0, "write output in advanced format" },
|
||||
{ oPassphrase, "passphrase", 2, "|STRING|use passphrase STRING" },
|
||||
{ oProtect, "protect", 256, "protect a private key"},
|
||||
{ oUnprotect, "unprotect", 256, "unprotect a private key"},
|
||||
{ oShadow, "shadow", 256, "create a shadow entry for a priblic key"},
|
||||
{ oShowShadowInfo, "show-shadow-info", 256, "return the shadow info"},
|
||||
{ oShowKeygrip, "show-keygrip", 256, "show the \"keygrip\""},
|
||||
|
||||
{ oP12Import, "p12-import", 256, "import a PKCS-12 encoded private key"},
|
||||
{ oP12Export, "p12-export", 256, "export a private key PKCS-12 encoded"},
|
||||
{ oStore, "store", 0, "store the created key in the appropriate place"},
|
||||
{ oForce, "force", 0, "force overwriting"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static const char *
|
||||
my_strusage (int level)
|
||||
{
|
||||
const char *p;
|
||||
switch (level)
|
||||
{
|
||||
case 11: p = "gpg-protect-tool (GnuPG)";
|
||||
break;
|
||||
case 13: p = VERSION; break;
|
||||
case 17: p = PRINTABLE_OS_NAME; break;
|
||||
case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
|
||||
break;
|
||||
case 1:
|
||||
case 40: p = _("Usage: gpg-protect-tool [options] (-h for help)\n");
|
||||
break;
|
||||
case 41: p = _("Syntax: gpg-protect-tool [options] [args]]\n"
|
||||
"Secret key maintenance tool\n");
|
||||
break;
|
||||
|
||||
default: p = NULL;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
i18n_init (void)
|
||||
{
|
||||
#ifdef USE_SIMPLE_GETTEXT
|
||||
set_gettext_file( PACKAGE );
|
||||
#else
|
||||
#ifdef ENABLE_NLS
|
||||
setlocale (LC_ALL, "");
|
||||
bindtextdomain (PACKAGE, LOCALEDIR);
|
||||
textdomain (PACKAGE);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Used by gcry for logging */
|
||||
static void
|
||||
my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
|
||||
{
|
||||
/* translate the log levels */
|
||||
switch (level)
|
||||
{
|
||||
case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
|
||||
case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
|
||||
case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
|
||||
case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
|
||||
case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
|
||||
case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break;
|
||||
case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
|
||||
default: level = JNLIB_LOG_ERROR; break; }
|
||||
log_logv (level, fmt, arg_ptr);
|
||||
}
|
||||
|
||||
|
||||
/* static void */
|
||||
/* print_mpi (const char *text, GcryMPI a) */
|
||||
/* { */
|
||||
/* char *buf; */
|
||||
/* void *bufaddr = &buf; */
|
||||
/* int rc; */
|
||||
|
||||
/* rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a); */
|
||||
/* if (rc) */
|
||||
/* log_info ("%s: [error printing number: %s]\n", text, gcry_strerror (rc)); */
|
||||
/* else */
|
||||
/* { */
|
||||
/* log_info ("%s: %s\n", text, buf); */
|
||||
/* gcry_free (buf); */
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
|
||||
|
||||
static unsigned char *
|
||||
make_canonical (const char *fname, const char *buf, size_t buflen)
|
||||
{
|
||||
int rc;
|
||||
size_t erroff, len;
|
||||
GCRY_SEXP sexp;
|
||||
unsigned char *result;
|
||||
|
||||
rc = gcry_sexp_sscan (&sexp, &erroff, buf, buflen);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("invalid S-Expression in `%s' (off=%u): %s\n",
|
||||
fname, (unsigned int)erroff, gcry_strerror (rc));
|
||||
return NULL;
|
||||
}
|
||||
len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||
assert (len);
|
||||
result = xmalloc (len);
|
||||
len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, result, len);
|
||||
assert (len);
|
||||
gcry_sexp_release (sexp);
|
||||
return result;
|
||||
}
|
||||
|
||||
static char *
|
||||
make_advanced (const unsigned char *buf, size_t buflen)
|
||||
{
|
||||
int rc;
|
||||
size_t erroff, len;
|
||||
GCRY_SEXP sexp;
|
||||
unsigned char *result;
|
||||
|
||||
rc = gcry_sexp_sscan (&sexp, &erroff, buf, buflen);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("invalid canonical S-Expression (off=%u): %s\n",
|
||||
(unsigned int)erroff, gcry_strerror (rc));
|
||||
return NULL;
|
||||
}
|
||||
len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
|
||||
assert (len);
|
||||
result = xmalloc (len);
|
||||
len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, len);
|
||||
assert (len);
|
||||
gcry_sexp_release (sexp);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
read_file (const char *fname, size_t *r_length)
|
||||
{
|
||||
FILE *fp;
|
||||
struct stat st;
|
||||
char *buf;
|
||||
size_t buflen;
|
||||
|
||||
fp = fopen (fname, "rb");
|
||||
if (!fp)
|
||||
{
|
||||
log_error ("can't open `%s': %s\n", fname, strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fstat (fileno(fp), &st))
|
||||
{
|
||||
log_error ("can't stat `%s': %s\n", fname, strerror (errno));
|
||||
fclose (fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buflen = st.st_size;
|
||||
buf = xmalloc (buflen+1);
|
||||
if (fread (buf, buflen, 1, fp) != 1)
|
||||
{
|
||||
log_error ("error reading `%s': %s\n", fname, strerror (errno));
|
||||
fclose (fp);
|
||||
xfree (buf);
|
||||
return NULL;
|
||||
}
|
||||
fclose (fp);
|
||||
|
||||
*r_length = buflen;
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
static unsigned char *
|
||||
read_key (const char *fname)
|
||||
{
|
||||
char *buf;
|
||||
size_t buflen;
|
||||
unsigned char *key;
|
||||
|
||||
buf = read_file (fname, &buflen);
|
||||
key = make_canonical (fname, buf, buflen);
|
||||
xfree (buf);
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
read_and_protect (const char *fname)
|
||||
{
|
||||
int rc;
|
||||
unsigned char *key;
|
||||
unsigned char *result;
|
||||
size_t resultlen;
|
||||
|
||||
key = read_key (fname);
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
rc = agent_protect (key, get_passphrase (), &result, &resultlen);
|
||||
xfree (key);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("protecting the key failed: %s\n", gnupg_strerror (rc));
|
||||
return;
|
||||
}
|
||||
|
||||
if (opt_armor)
|
||||
{
|
||||
char *p = make_advanced (result, resultlen);
|
||||
xfree (result);
|
||||
if (!p)
|
||||
return;
|
||||
result = p;
|
||||
resultlen = strlen (p);
|
||||
}
|
||||
|
||||
fwrite (result, resultlen, 1, stdout);
|
||||
xfree (result);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
read_and_unprotect (const char *fname)
|
||||
{
|
||||
int rc;
|
||||
unsigned char *key;
|
||||
unsigned char *result;
|
||||
size_t resultlen;
|
||||
|
||||
key = read_key (fname);
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
rc = agent_unprotect (key, get_passphrase (), &result, &resultlen);
|
||||
xfree (key);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("unprotecting the key failed: %s\n", gnupg_strerror (rc));
|
||||
return;
|
||||
}
|
||||
|
||||
if (opt_armor)
|
||||
{
|
||||
char *p = make_advanced (result, resultlen);
|
||||
xfree (result);
|
||||
if (!p)
|
||||
return;
|
||||
result = p;
|
||||
resultlen = strlen (p);
|
||||
}
|
||||
|
||||
fwrite (result, resultlen, 1, stdout);
|
||||
xfree (result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
read_and_shadow (const char *fname)
|
||||
{
|
||||
int rc;
|
||||
unsigned char *key;
|
||||
unsigned char *result;
|
||||
size_t resultlen;
|
||||
|
||||
key = read_key (fname);
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
rc = agent_shadow_key (key, "(8:313233342:43)", &result);
|
||||
xfree (key);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("shadowing the key failed: %s\n", gnupg_strerror (rc));
|
||||
return;
|
||||
}
|
||||
resultlen = gcry_sexp_canon_len (result, 0, NULL,NULL);
|
||||
assert (resultlen);
|
||||
|
||||
if (opt_armor)
|
||||
{
|
||||
char *p = make_advanced (result, resultlen);
|
||||
xfree (result);
|
||||
if (!p)
|
||||
return;
|
||||
result = p;
|
||||
resultlen = strlen (p);
|
||||
}
|
||||
|
||||
fwrite (result, resultlen, 1, stdout);
|
||||
xfree (result);
|
||||
}
|
||||
|
||||
static void
|
||||
show_shadow_info (const char *fname)
|
||||
{
|
||||
int rc;
|
||||
unsigned char *key;
|
||||
const unsigned char *info;
|
||||
size_t infolen;
|
||||
|
||||
key = read_key (fname);
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
rc = agent_get_shadow_info (key, &info);
|
||||
xfree (key);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("get_shadow_info failed: %s\n", gnupg_strerror (rc));
|
||||
return;
|
||||
}
|
||||
infolen = gcry_sexp_canon_len (info, 0, NULL,NULL);
|
||||
assert (infolen);
|
||||
|
||||
if (opt_armor)
|
||||
{
|
||||
char *p = make_advanced (info, infolen);
|
||||
if (!p)
|
||||
return;
|
||||
fwrite (p, strlen (p), 1, stdout);
|
||||
xfree (p);
|
||||
}
|
||||
else
|
||||
fwrite (info, infolen, 1, stdout);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
show_file (const char *fname)
|
||||
{
|
||||
unsigned char *key;
|
||||
size_t keylen;
|
||||
char *p;
|
||||
|
||||
key = read_key (fname);
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
keylen = gcry_sexp_canon_len (key, 0, NULL,NULL);
|
||||
assert (keylen);
|
||||
|
||||
p = make_advanced (key, keylen);
|
||||
xfree (key);
|
||||
if (p)
|
||||
{
|
||||
fwrite (p, strlen (p), 1, stdout);
|
||||
xfree (p);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
show_keygrip (const char *fname)
|
||||
{
|
||||
unsigned char *key;
|
||||
GcrySexp private;
|
||||
unsigned char grip[20];
|
||||
int i;
|
||||
|
||||
key = read_key (fname);
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
if (gcry_sexp_new (&private, key, 0, 0))
|
||||
{
|
||||
log_error ("gcry_sexp_new failed\n");
|
||||
return;
|
||||
}
|
||||
xfree (key);
|
||||
|
||||
if (!gcry_pk_get_keygrip (private, grip))
|
||||
{
|
||||
log_error ("can't calculate keygrip\n");
|
||||
return;
|
||||
}
|
||||
gcry_sexp_release (private);
|
||||
|
||||
for (i=0; i < 20; i++)
|
||||
printf ("%02X", grip[i]);
|
||||
putchar ('\n');
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
rsa_key_check (struct rsa_secret_key_s *skey)
|
||||
{
|
||||
int err = 0;
|
||||
MPI t = gcry_mpi_snew (0);
|
||||
MPI t1 = gcry_mpi_snew (0);
|
||||
MPI t2 = gcry_mpi_snew (0);
|
||||
MPI phi = gcry_mpi_snew (0);
|
||||
|
||||
/* check that n == p * q */
|
||||
gcry_mpi_mul (t, skey->p, skey->q);
|
||||
if (gcry_mpi_cmp( t, skey->n) )
|
||||
{
|
||||
log_error ("RSA oops: n != p * q\n");
|
||||
err++;
|
||||
}
|
||||
|
||||
/* check that p is less than q */
|
||||
if (gcry_mpi_cmp (skey->p, skey->q) > 0)
|
||||
{
|
||||
GcryMPI tmp;
|
||||
|
||||
log_info ("swapping secret primes\n");
|
||||
tmp = gcry_mpi_copy (skey->p);
|
||||
gcry_mpi_set (skey->p, skey->q);
|
||||
gcry_mpi_set (skey->q, tmp);
|
||||
gcry_mpi_release (tmp);
|
||||
/* and must recompute u of course */
|
||||
gcry_mpi_invm (skey->u, skey->p, skey->q);
|
||||
}
|
||||
|
||||
/* check that e divides neither p-1 nor q-1 */
|
||||
gcry_mpi_sub_ui (t, skey->p, 1 );
|
||||
gcry_mpi_div (NULL, t, t, skey->e, 0);
|
||||
if (!gcry_mpi_cmp_ui( t, 0) )
|
||||
{
|
||||
log_error ("RSA oops: e divides p-1\n");
|
||||
err++;
|
||||
}
|
||||
gcry_mpi_sub_ui (t, skey->q, 1);
|
||||
gcry_mpi_div (NULL, t, t, skey->e, 0);
|
||||
if (!gcry_mpi_cmp_ui( t, 0))
|
||||
{
|
||||
log_info ( "RSA oops: e divides q-1\n" );
|
||||
err++;
|
||||
}
|
||||
|
||||
/* check that d is correct. */
|
||||
gcry_mpi_sub_ui (t1, skey->p, 1);
|
||||
gcry_mpi_sub_ui (t2, skey->q, 1);
|
||||
gcry_mpi_mul (phi, t1, t2);
|
||||
gcry_mpi_invm (t, skey->e, phi);
|
||||
if (gcry_mpi_cmp (t, skey->d))
|
||||
{ /* no: try universal exponent. */
|
||||
gcry_mpi_gcd (t, t1, t2);
|
||||
gcry_mpi_div (t, NULL, phi, t, 0);
|
||||
gcry_mpi_invm (t, skey->e, t);
|
||||
if (gcry_mpi_cmp (t, skey->d))
|
||||
{
|
||||
log_error ("RSA oops: bad secret exponent\n");
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for correctness of u */
|
||||
gcry_mpi_invm (t, skey->p, skey->q);
|
||||
if (gcry_mpi_cmp (t, skey->u))
|
||||
{
|
||||
log_info ( "RSA oops: bad u parameter\n");
|
||||
err++;
|
||||
}
|
||||
|
||||
if (err)
|
||||
log_info ("RSA secret key check failed\n");
|
||||
|
||||
gcry_mpi_release (t);
|
||||
gcry_mpi_release (t1);
|
||||
gcry_mpi_release (t2);
|
||||
gcry_mpi_release (phi);
|
||||
|
||||
return err? -1:0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
import_p12_file (const char *fname)
|
||||
{
|
||||
char *buf;
|
||||
unsigned char *result;
|
||||
size_t buflen, resultlen;
|
||||
int i;
|
||||
int rc;
|
||||
GcryMPI *kparms;
|
||||
struct rsa_secret_key_s sk;
|
||||
GcrySexp s_key;
|
||||
unsigned char *key;
|
||||
unsigned char grip[20];
|
||||
|
||||
/* fixme: we should release some stuff on error */
|
||||
|
||||
buf = read_file (fname, &buflen);
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
kparms = p12_parse (buf, buflen, get_passphrase ());
|
||||
xfree (buf);
|
||||
if (!kparms)
|
||||
{
|
||||
log_error ("error parsing or decrypting the PKCS-1 file\n");
|
||||
return;
|
||||
}
|
||||
for (i=0; kparms[i]; i++)
|
||||
;
|
||||
if (i != 8)
|
||||
{
|
||||
log_error ("invalid structure of private key\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* print_mpi (" n", kparms[0]); */
|
||||
/* print_mpi (" e", kparms[1]); */
|
||||
/* print_mpi (" d", kparms[2]); */
|
||||
/* print_mpi (" p", kparms[3]); */
|
||||
/* print_mpi (" q", kparms[4]); */
|
||||
/* print_mpi ("dmp1", kparms[5]); */
|
||||
/* print_mpi ("dmq1", kparms[6]); */
|
||||
/* print_mpi (" u", kparms[7]); */
|
||||
|
||||
sk.n = kparms[0];
|
||||
sk.e = kparms[1];
|
||||
sk.d = kparms[2];
|
||||
sk.q = kparms[3];
|
||||
sk.p = kparms[4];
|
||||
sk.u = kparms[7];
|
||||
if (rsa_key_check (&sk))
|
||||
return;
|
||||
/* print_mpi (" n", sk.n); */
|
||||
/* print_mpi (" e", sk.e); */
|
||||
/* print_mpi (" d", sk.d); */
|
||||
/* print_mpi (" p", sk.p); */
|
||||
/* print_mpi (" q", sk.q); */
|
||||
/* print_mpi (" u", sk.u); */
|
||||
|
||||
/* Create an S-expresion from the parameters. */
|
||||
rc = gcry_sexp_build (&s_key, NULL,
|
||||
"(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
|
||||
sk.n, sk.e, sk.d, sk.p, sk.q, sk.u, NULL);
|
||||
for (i=0; i < 8; i++)
|
||||
gcry_mpi_release (kparms[i]);
|
||||
gcry_free (kparms);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("failed to created S-expression from key: %s\n",
|
||||
gcry_strerror (rc));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Compute the keygrip. */
|
||||
if (!gcry_pk_get_keygrip (s_key, grip))
|
||||
{
|
||||
log_error ("can't calculate keygrip\n");
|
||||
return;
|
||||
}
|
||||
log_info ("keygrip: ");
|
||||
for (i=0; i < 20; i++)
|
||||
log_printf ("%02X", grip[i]);
|
||||
log_printf ("\n");
|
||||
|
||||
/* convert to canonical encoding */
|
||||
buflen = gcry_sexp_sprint (s_key, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||
assert (buflen);
|
||||
key = gcry_xmalloc_secure (buflen);
|
||||
buflen = gcry_sexp_sprint (s_key, GCRYSEXP_FMT_CANON, key, buflen);
|
||||
assert (buflen);
|
||||
gcry_sexp_release (s_key);
|
||||
|
||||
|
||||
rc = agent_protect (key, get_passphrase (), &result, &resultlen);
|
||||
xfree (key);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("protecting the key failed: %s\n", gnupg_strerror (rc));
|
||||
return;
|
||||
}
|
||||
|
||||
if (opt_armor)
|
||||
{
|
||||
char *p = make_advanced (result, resultlen);
|
||||
xfree (result);
|
||||
if (!p)
|
||||
return;
|
||||
result = p;
|
||||
resultlen = strlen (p);
|
||||
}
|
||||
|
||||
if (opt_store)
|
||||
store_private_key (grip, result, resultlen, opt_force);
|
||||
else
|
||||
fwrite (result, resultlen, 1, stdout);
|
||||
|
||||
xfree (result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static GcryMPI *
|
||||
sexp_to_kparms (GCRY_SEXP sexp)
|
||||
{
|
||||
GcrySexp list, l2;
|
||||
const char *name;
|
||||
const char *s;
|
||||
size_t n;
|
||||
int i, idx;
|
||||
const char *elems;
|
||||
GcryMPI *array;
|
||||
|
||||
list = gcry_sexp_find_token (sexp, "private-key", 0 );
|
||||
if(!list)
|
||||
return NULL;
|
||||
l2 = gcry_sexp_cadr (list);
|
||||
gcry_sexp_release (list);
|
||||
list = l2;
|
||||
name = gcry_sexp_nth_data (list, 0, &n);
|
||||
if(!name || n != 3 || memcmp (name, "rsa", 3))
|
||||
{
|
||||
gcry_sexp_release (list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Paramter names used with RSA. */
|
||||
elems = "nedpqu";
|
||||
array = xcalloc (strlen(elems) + 1, sizeof *array);
|
||||
for (idx=0, s=elems; *s; s++, idx++ )
|
||||
{
|
||||
l2 = gcry_sexp_find_token (list, s, 1);
|
||||
if (!l2)
|
||||
{
|
||||
for (i=0; i<idx; i++)
|
||||
gcry_mpi_release (array[i]);
|
||||
xfree (array);
|
||||
gcry_sexp_release (list);
|
||||
return NULL; /* required parameter not found */
|
||||
}
|
||||
array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
|
||||
gcry_sexp_release (l2);
|
||||
if (!array[idx])
|
||||
{
|
||||
for (i=0; i<idx; i++)
|
||||
gcry_mpi_release (array[i]);
|
||||
xfree (array);
|
||||
gcry_sexp_release (list);
|
||||
return NULL; /* required parameter is invalid */
|
||||
}
|
||||
}
|
||||
|
||||
gcry_sexp_release (list);
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
export_p12_file (const char *fname)
|
||||
{
|
||||
GcryMPI kparms[9], *kp;
|
||||
unsigned char *key;
|
||||
size_t keylen;
|
||||
GcrySexp private;
|
||||
struct rsa_secret_key_s sk;
|
||||
int i;
|
||||
|
||||
key = read_key (fname);
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
if (gcry_sexp_new (&private, key, 0, 0))
|
||||
{
|
||||
log_error ("gcry_sexp_new failed\n");
|
||||
return;
|
||||
}
|
||||
xfree (key);
|
||||
|
||||
kp = sexp_to_kparms (private);
|
||||
gcry_sexp_release (private);
|
||||
if (!kp)
|
||||
{
|
||||
log_error ("error converting key parameters\n");
|
||||
return;
|
||||
}
|
||||
sk.n = kp[0];
|
||||
sk.e = kp[1];
|
||||
sk.d = kp[2];
|
||||
sk.p = kp[3];
|
||||
sk.q = kp[4];
|
||||
sk.u = kp[5];
|
||||
xfree (kp);
|
||||
|
||||
|
||||
kparms[0] = sk.n;
|
||||
kparms[1] = sk.e;
|
||||
kparms[2] = sk.d;
|
||||
kparms[3] = sk.q;
|
||||
kparms[4] = sk.p;
|
||||
kparms[5] = gcry_mpi_snew (0); /* compute d mod (p-1) */
|
||||
gcry_mpi_sub_ui (kparms[5], kparms[3], 1);
|
||||
gcry_mpi_mod (kparms[5], sk.d, kparms[5]);
|
||||
kparms[6] = gcry_mpi_snew (0); /* compute d mod (q-1) */
|
||||
gcry_mpi_sub_ui (kparms[6], kparms[4], 1);
|
||||
gcry_mpi_mod (kparms[6], sk.d, kparms[6]);
|
||||
kparms[7] = sk.u;
|
||||
kparms[8] = NULL;
|
||||
|
||||
key = p12_build (kparms, get_passphrase (), &keylen);
|
||||
for (i=0; i < 8; i++)
|
||||
gcry_mpi_release (kparms[i]);
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
fwrite (key, keylen, 1, stdout);
|
||||
xfree (key);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char **argv )
|
||||
{
|
||||
ARGPARSE_ARGS pargs;
|
||||
int cmd = 0;
|
||||
|
||||
set_strusage (my_strusage);
|
||||
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
|
||||
log_set_prefix ("gpg-protect-tool", 1);
|
||||
i18n_init ();
|
||||
|
||||
if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
|
||||
{
|
||||
log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
|
||||
NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
|
||||
}
|
||||
|
||||
gcry_set_log_handler (my_gcry_logger, NULL);
|
||||
|
||||
gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
|
||||
|
||||
pargs.argc = &argc;
|
||||
pargs.argv = &argv;
|
||||
pargs.flags= 1; /* do not remove the args */
|
||||
while (arg_parse (&pargs, opts) )
|
||||
{
|
||||
switch (pargs.r_opt)
|
||||
{
|
||||
case oVerbose: opt.verbose++; break;
|
||||
case oArmor: opt_armor=1; break;
|
||||
|
||||
case oProtect: cmd = oProtect; break;
|
||||
case oUnprotect: cmd = oUnprotect; break;
|
||||
case oShadow: cmd = oShadow; break;
|
||||
case oShowShadowInfo: cmd = oShowShadowInfo; break;
|
||||
case oShowKeygrip: cmd = oShowKeygrip; break;
|
||||
case oP12Import: cmd = oP12Import; break;
|
||||
case oP12Export: cmd = oP12Export; break;
|
||||
|
||||
case oPassphrase: passphrase = pargs.r.ret_str; break;
|
||||
case oStore: opt_store = 1; break;
|
||||
case oForce: opt_force = 1; break;
|
||||
|
||||
default : pargs.err = 2; break;
|
||||
}
|
||||
}
|
||||
if (log_get_errorcount(0))
|
||||
exit(2);
|
||||
|
||||
if (argc != 1)
|
||||
usage (1);
|
||||
|
||||
if (cmd == oProtect)
|
||||
read_and_protect (*argv);
|
||||
else if (cmd == oUnprotect)
|
||||
read_and_unprotect (*argv);
|
||||
else if (cmd == oShadow)
|
||||
read_and_shadow (*argv);
|
||||
else if (cmd == oShowShadowInfo)
|
||||
show_shadow_info (*argv);
|
||||
else if (cmd == oShowKeygrip)
|
||||
show_keygrip (*argv);
|
||||
else if (cmd == oP12Import)
|
||||
import_p12_file (*argv);
|
||||
else if (cmd == oP12Export)
|
||||
export_p12_file (*argv);
|
||||
else
|
||||
show_file (*argv);
|
||||
|
||||
agent_exit (0);
|
||||
return 8; /*NOTREACHED*/
|
||||
}
|
||||
|
||||
void
|
||||
agent_exit (int rc)
|
||||
{
|
||||
rc = rc? rc : log_get_errorcount(0)? 2 : 0;
|
||||
exit (rc);
|
||||
}
|
||||
|
||||
|
||||
/* Return the passphrase string and ask the agent if it has not been
|
||||
set from the command line. */
|
||||
static const char *
|
||||
get_passphrase (void)
|
||||
{
|
||||
char *pw;
|
||||
int err;
|
||||
|
||||
if (passphrase)
|
||||
return passphrase;
|
||||
|
||||
pw = simple_pwquery (NULL,NULL,
|
||||
_("Enter passphrase:"),
|
||||
_("Please enter the passphrase or the PIN\n"
|
||||
"needed to complete this operation."),
|
||||
&err);
|
||||
if (!pw)
|
||||
{
|
||||
if (err)
|
||||
log_error ("error while asking for the passphrase\n");
|
||||
else
|
||||
log_info ("cancelled\n");
|
||||
agent_exit (0);
|
||||
}
|
||||
passphrase = pw;
|
||||
return passphrase;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
store_private_key (const unsigned char *grip,
|
||||
const void *buffer, size_t length, int force)
|
||||
{
|
||||
int i;
|
||||
const char *homedir;
|
||||
char *fname;
|
||||
FILE *fp;
|
||||
char hexgrip[40+4+1];
|
||||
|
||||
for (i=0; i < 20; i++)
|
||||
sprintf (hexgrip+2*i, "%02X", grip[i]);
|
||||
strcpy (hexgrip+40, ".key");
|
||||
|
||||
homedir = getenv("GNUPGHOME");
|
||||
if (!homedir || !*homedir)
|
||||
homedir = GNUPG_DEFAULT_HOMEDIR;
|
||||
|
||||
fname = make_filename (homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
|
||||
if (force)
|
||||
fp = fopen (fname, "wb");
|
||||
else
|
||||
{
|
||||
if (!access (fname, F_OK))
|
||||
{
|
||||
log_error ("secret key file `%s' already exists\n", fname);
|
||||
xfree (fname);
|
||||
return -1;
|
||||
}
|
||||
fp = fopen (fname, "wbx"); /* FIXME: the x is a GNU extension - let
|
||||
configure check whether this actually
|
||||
works */
|
||||
}
|
||||
|
||||
if (!fp)
|
||||
{
|
||||
log_error ("can't create `%s': %s\n", fname, strerror (errno));
|
||||
xfree (fname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fwrite (buffer, length, 1, fp) != 1)
|
||||
{
|
||||
log_error ("error writing `%s': %s\n", fname, strerror (errno));
|
||||
fclose (fp);
|
||||
remove (fname);
|
||||
xfree (fname);
|
||||
return -1;
|
||||
}
|
||||
if ( fclose (fp) )
|
||||
{
|
||||
log_error ("error closing `%s': %s\n", fname, strerror (errno));
|
||||
remove (fname);
|
||||
xfree (fname);
|
||||
return -1;
|
||||
}
|
||||
log_info ("secret key stored as `%s'\n", fname);
|
||||
|
||||
xfree (fname);
|
||||
return 0;
|
||||
}
|
967
agent/protect.c
967
agent/protect.c
@ -1,967 +0,0 @@
|
||||
/* protect.c - Un/Protect a secret key
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 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 <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "agent.h"
|
||||
|
||||
#include "sexp-parse.h"
|
||||
|
||||
#define PROT_CIPHER GCRY_CIPHER_AES
|
||||
#define PROT_CIPHER_STRING "aes"
|
||||
#define PROT_CIPHER_KEYLEN (128/8)
|
||||
|
||||
|
||||
/* A table containing the information needed to create a protected
|
||||
private key */
|
||||
static struct {
|
||||
const char *algo;
|
||||
const char *parmlist;
|
||||
int prot_from, prot_to;
|
||||
} protect_info[] = {
|
||||
{ "rsa", "nedpqu", 2, 5 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
hash_passphrase (const char *passphrase, int hashalgo,
|
||||
int s2kmode,
|
||||
const unsigned char *s2ksalt, unsigned long s2kcount,
|
||||
unsigned char *key, size_t keylen);
|
||||
|
||||
|
||||
|
||||
/* Calculate the MIC for a private key S-Exp. SHA1HASH should pint to
|
||||
a 20 byte buffer. This function is suitable for any algorithms. */
|
||||
static int
|
||||
calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
|
||||
{
|
||||
const unsigned char *hash_begin, *hash_end;
|
||||
const unsigned char *s;
|
||||
size_t n;
|
||||
|
||||
s = plainkey;
|
||||
if (*s != '(')
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
if (!smatch (&s, n, "private-key"))
|
||||
return GNUPG_Unknown_Sexp;
|
||||
if (*s != '(')
|
||||
return GNUPG_Unknown_Sexp;
|
||||
hash_begin = s;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s += n; /* skip over the algorithm name */
|
||||
|
||||
while (*s == '(')
|
||||
{
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s += n;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s += n;
|
||||
if ( *s != ')' )
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s++;
|
||||
}
|
||||
if (*s != ')')
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s++;
|
||||
hash_end = s;
|
||||
|
||||
gcry_md_hash_buffer (GCRY_MD_SHA1, sha1hash,
|
||||
hash_begin, hash_end - hash_begin);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Encrypt the parameter block starting at PROTBEGIN with length
|
||||
PROTLEN using the utf8 encoded key PASSPHRASE and return the entire
|
||||
encrypted block in RESULT or ereturn with an error code. SHA1HASH
|
||||
is the 20 byte SHA-1 hash required for the integrity code.
|
||||
|
||||
The parameter block is expected to be an incomplete S-Expression of
|
||||
the form (example in advanced format):
|
||||
|
||||
(d #046129F..[some bytes not shown]..81#)
|
||||
(p #00e861b..[some bytes not shown]..f1#)
|
||||
(q #00f7a7c..[some bytes not shown]..61#)
|
||||
(u #304559a..[some bytes not shown]..9b#)
|
||||
|
||||
the returned block is the S-Expression:
|
||||
|
||||
(protected mode (parms) encrypted_octet_string)
|
||||
|
||||
*/
|
||||
static int
|
||||
do_encryption (const char *protbegin, size_t protlen,
|
||||
const char *passphrase, const unsigned char *sha1hash,
|
||||
unsigned char **result, size_t *resultlen)
|
||||
{
|
||||
GCRY_CIPHER_HD hd;
|
||||
const char *modestr = "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc";
|
||||
int blklen, enclen, outlen;
|
||||
char *iv = NULL;
|
||||
int rc = 0;
|
||||
char *outbuf = NULL;
|
||||
char *p;
|
||||
int saltpos, ivpos, encpos;
|
||||
|
||||
hd = gcry_cipher_open (PROT_CIPHER, GCRY_CIPHER_MODE_CBC,
|
||||
GCRY_CIPHER_SECURE);
|
||||
if (!hd)
|
||||
return map_gcry_err (gcry_errno());
|
||||
|
||||
|
||||
/* We need to work on a copy of the data because this makes it
|
||||
easier to add the trailer and the padding and more important we
|
||||
have to prefix the text with 2 parenthesis, so we have to
|
||||
allocate enough space for:
|
||||
|
||||
((<parameter_list>)(4:hash4:sha120:<hashvalue>)) + padding
|
||||
|
||||
We always append a full block of random bytes as padding but
|
||||
encrypt only what is needed for a full blocksize */
|
||||
blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER);
|
||||
outlen = 2 + protlen + 2 + 6 + 6 + 23 + 2 + blklen;
|
||||
enclen = outlen/blklen * blklen;
|
||||
outbuf = gcry_malloc_secure (outlen);
|
||||
if (!outbuf)
|
||||
rc = GNUPG_Out_Of_Core;
|
||||
if (!rc)
|
||||
{
|
||||
/* allocate random bytes to be used as IV, padding and s2k salt*/
|
||||
iv = gcry_random_bytes (blklen*2+8, GCRY_WEAK_RANDOM);
|
||||
if (!iv)
|
||||
rc = GNUPG_Out_Of_Core;
|
||||
else
|
||||
rc = gcry_cipher_setiv (hd, iv, blklen);
|
||||
}
|
||||
if (!rc)
|
||||
{
|
||||
unsigned char *key;
|
||||
size_t keylen = PROT_CIPHER_KEYLEN;
|
||||
|
||||
key = gcry_malloc_secure (keylen);
|
||||
if (!key)
|
||||
rc = GNUPG_Out_Of_Core;
|
||||
else
|
||||
{
|
||||
rc = hash_passphrase (passphrase, GCRY_MD_SHA1,
|
||||
3, iv+2*blklen, 96, key, keylen);
|
||||
if (!rc)
|
||||
rc = gcry_cipher_setkey (hd, key, keylen);
|
||||
xfree (key);
|
||||
}
|
||||
}
|
||||
if (!rc)
|
||||
{
|
||||
p = outbuf;
|
||||
*p++ = '(';
|
||||
*p++ = '(';
|
||||
memcpy (p, protbegin, protlen);
|
||||
p += protlen;
|
||||
memcpy (p, ")(4:hash4:sha120:", 17);
|
||||
p += 17;
|
||||
memcpy (p, sha1hash, 20);
|
||||
p += 20;
|
||||
*p++ = ')';
|
||||
*p++ = ')';
|
||||
memcpy (p, iv+blklen, blklen);
|
||||
p += blklen;
|
||||
assert ( p - outbuf == outlen);
|
||||
rc = gcry_cipher_encrypt (hd, outbuf, enclen, NULL, 0);
|
||||
}
|
||||
gcry_cipher_close (hd);
|
||||
if (rc)
|
||||
{
|
||||
xfree (iv);
|
||||
xfree (outbuf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Now allocate the buffer we want to return. This is
|
||||
|
||||
(protected openpgp-s2k3-sha1-aes-cbc
|
||||
((sha1 salt no_of_iterations) 16byte_iv)
|
||||
encrypted_octet_string)
|
||||
|
||||
in canoncical format of course. We use asprintf and %n modifier
|
||||
and spaces as palceholders. */
|
||||
asprintf (&p,
|
||||
"(9:protected%d:%s((4:sha18:%n_8bytes_2:96)%d:%n%*s)%d:%n%*s)",
|
||||
(int)strlen (modestr), modestr,
|
||||
&saltpos,
|
||||
blklen, &ivpos, blklen, "",
|
||||
enclen, &encpos, enclen, "");
|
||||
if (p)
|
||||
{ /* asprintf does not use out malloc system */
|
||||
char *psave = p;
|
||||
p = xtrymalloc (strlen (psave)+1);
|
||||
if (p)
|
||||
strcpy (p, psave);
|
||||
free (psave);
|
||||
}
|
||||
if (!p)
|
||||
{
|
||||
xfree (iv);
|
||||
xfree (outbuf);
|
||||
return GNUPG_Out_Of_Core;
|
||||
}
|
||||
*resultlen = strlen (p);
|
||||
*result = p;
|
||||
memcpy (p+saltpos, iv+2*blklen, 8);
|
||||
memcpy (p+ivpos, iv, blklen);
|
||||
memcpy (p+encpos, outbuf, enclen);
|
||||
xfree (iv);
|
||||
xfree (outbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Protect the key encoded in canonical format in plainkey. We assume
|
||||
a valid S-Exp here. */
|
||||
int
|
||||
agent_protect (const unsigned char *plainkey, const char *passphrase,
|
||||
unsigned char **result, size_t *resultlen)
|
||||
{
|
||||
int rc;
|
||||
const unsigned char *s;
|
||||
const unsigned char *hash_begin, *hash_end;
|
||||
const unsigned char *prot_begin, *prot_end, *real_end;
|
||||
size_t n;
|
||||
int c, infidx, i;
|
||||
unsigned char hashvalue[20];
|
||||
unsigned char *protected;
|
||||
size_t protectedlen;
|
||||
int depth = 0;
|
||||
unsigned char *p;
|
||||
|
||||
s = plainkey;
|
||||
if (*s != '(')
|
||||
return GNUPG_Invalid_Sexp;
|
||||
depth++;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
if (!smatch (&s, n, "private-key"))
|
||||
return GNUPG_Unknown_Sexp;
|
||||
if (*s != '(')
|
||||
return GNUPG_Unknown_Sexp;
|
||||
depth++;
|
||||
hash_begin = s;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
|
||||
for (infidx=0; protect_info[infidx].algo
|
||||
&& !smatch (&s, n, protect_info[infidx].algo); infidx++)
|
||||
;
|
||||
if (!protect_info[infidx].algo)
|
||||
return GNUPG_Unsupported_Algorithm;
|
||||
|
||||
prot_begin = prot_end = NULL;
|
||||
for (i=0; (c=protect_info[infidx].parmlist[i]); i++)
|
||||
{
|
||||
if (i == protect_info[infidx].prot_from)
|
||||
prot_begin = s;
|
||||
if (*s != '(')
|
||||
return GNUPG_Invalid_Sexp;
|
||||
depth++;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
if (n != 1 || c != *s)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s += n;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s +=n; /* skip value */
|
||||
if (*s != ')')
|
||||
return GNUPG_Invalid_Sexp;
|
||||
depth--;
|
||||
if (i == protect_info[infidx].prot_to)
|
||||
prot_end = s;
|
||||
s++;
|
||||
}
|
||||
if (*s != ')' || !prot_begin || !prot_end )
|
||||
return GNUPG_Invalid_Sexp;
|
||||
depth--;
|
||||
hash_end = s;
|
||||
s++;
|
||||
/* skip to the end of the S-exp */
|
||||
assert (depth == 1);
|
||||
rc = sskip (&s, &depth);
|
||||
if (rc)
|
||||
return rc;
|
||||
assert (!depth);
|
||||
real_end = s-1;
|
||||
|
||||
gcry_md_hash_buffer (GCRY_MD_SHA1, hashvalue,
|
||||
hash_begin, hash_end - hash_begin + 1);
|
||||
|
||||
rc = do_encryption (prot_begin, prot_end - prot_begin + 1,
|
||||
passphrase, hashvalue,
|
||||
&protected, &protectedlen);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Now create the protected version of the key. Note that the 10
|
||||
extra bytes are for for the inserted "protected-" string (the
|
||||
beginning of the plaintext reads: "((11:private-key(" ). */
|
||||
*resultlen = (10
|
||||
+ (prot_begin-plainkey)
|
||||
+ protectedlen
|
||||
+ (real_end-prot_end));
|
||||
*result = p = xtrymalloc (*resultlen);
|
||||
if (!p)
|
||||
{
|
||||
xfree (protected);
|
||||
return GNUPG_Out_Of_Core;
|
||||
}
|
||||
memcpy (p, "(21:protected-", 14);
|
||||
p += 14;
|
||||
memcpy (p, plainkey+4, prot_begin - plainkey - 4);
|
||||
p += prot_begin - plainkey - 4;
|
||||
memcpy (p, protected, protectedlen);
|
||||
p += protectedlen;
|
||||
memcpy (p, prot_end+1, real_end - prot_end);
|
||||
p += real_end - prot_end;
|
||||
assert ( p - *result == *resultlen);
|
||||
xfree (protected);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Do the actual decryption and check the return list for consistency. */
|
||||
static int
|
||||
do_decryption (const unsigned char *protected, size_t protectedlen,
|
||||
const char *passphrase,
|
||||
const unsigned char *s2ksalt, unsigned long s2kcount,
|
||||
const unsigned char *iv, size_t ivlen,
|
||||
unsigned char **result)
|
||||
{
|
||||
int rc = 0;
|
||||
int blklen;
|
||||
GCRY_CIPHER_HD hd;
|
||||
unsigned char *outbuf;
|
||||
size_t reallen;
|
||||
|
||||
blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER);
|
||||
if (protectedlen < 4 || (protectedlen%blklen))
|
||||
return GNUPG_Corrupted_Protection;
|
||||
|
||||
hd = gcry_cipher_open (PROT_CIPHER, GCRY_CIPHER_MODE_CBC,
|
||||
GCRY_CIPHER_SECURE);
|
||||
if (!hd)
|
||||
return map_gcry_err (gcry_errno());
|
||||
|
||||
outbuf = gcry_malloc_secure (protectedlen);
|
||||
if (!outbuf)
|
||||
rc = GNUPG_Out_Of_Core;
|
||||
if (!rc)
|
||||
rc = gcry_cipher_setiv (hd, iv, ivlen);
|
||||
if (!rc)
|
||||
{
|
||||
unsigned char *key;
|
||||
size_t keylen = PROT_CIPHER_KEYLEN;
|
||||
|
||||
key = gcry_malloc_secure (keylen);
|
||||
if (!key)
|
||||
rc = GNUPG_Out_Of_Core;
|
||||
else
|
||||
{
|
||||
rc = hash_passphrase (passphrase, GCRY_MD_SHA1,
|
||||
3, s2ksalt, s2kcount, key, keylen);
|
||||
if (!rc)
|
||||
rc = gcry_cipher_setkey (hd, key, keylen);
|
||||
xfree (key);
|
||||
}
|
||||
}
|
||||
if (!rc)
|
||||
rc = gcry_cipher_decrypt (hd, outbuf, protectedlen,
|
||||
protected, protectedlen);
|
||||
gcry_cipher_close (hd);
|
||||
if (rc)
|
||||
{
|
||||
xfree (outbuf);
|
||||
return rc;
|
||||
}
|
||||
/* do a quick check first */
|
||||
if (*outbuf != '(' && outbuf[1] != '(')
|
||||
{
|
||||
xfree (outbuf);
|
||||
return GNUPG_Bad_Passphrase;
|
||||
}
|
||||
/* check that we have a consistent S-Exp */
|
||||
reallen = gcry_sexp_canon_len (outbuf, protectedlen, NULL, NULL);
|
||||
if (!reallen || (reallen + blklen < protectedlen) )
|
||||
{
|
||||
xfree (outbuf);
|
||||
return GNUPG_Bad_Passphrase;
|
||||
}
|
||||
*result = outbuf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Merge the parameter list contained in CLEARTEXT with the original
|
||||
protect lists PROTECTEDKEY by replacing the list at REPLACEPOS.
|
||||
Return the new list in RESULT and the MIC value in the 20 byte
|
||||
buffer SHA1HASH. */
|
||||
static int
|
||||
merge_lists (const unsigned char *protectedkey,
|
||||
size_t replacepos,
|
||||
const unsigned char *cleartext,
|
||||
unsigned char *sha1hash, unsigned char **result)
|
||||
{
|
||||
size_t n, newlistlen;
|
||||
unsigned char *newlist, *p;
|
||||
const unsigned char *s;
|
||||
const unsigned char *startpos, *endpos;
|
||||
int i, rc;
|
||||
|
||||
if (replacepos < 26)
|
||||
return GNUPG_Bug;
|
||||
|
||||
/* Estimate the required size of the resulting list. We have a large
|
||||
safety margin of >20 bytes (MIC hash from CLEARTEXT and the
|
||||
removed "protected-" */
|
||||
newlistlen = gcry_sexp_canon_len (protectedkey, 0, NULL, NULL);
|
||||
if (!newlistlen)
|
||||
return GNUPG_Bug;
|
||||
n = gcry_sexp_canon_len (cleartext, 0, NULL, NULL);
|
||||
if (!n)
|
||||
return GNUPG_Bug;
|
||||
newlistlen += n;
|
||||
newlist = gcry_malloc_secure (newlistlen);
|
||||
if (!newlist)
|
||||
return GNUPG_Out_Of_Core;
|
||||
|
||||
/* Copy the initial segment */
|
||||
strcpy (newlist, "(11:private-key");
|
||||
p = newlist + 15;
|
||||
memcpy (p, protectedkey+15+10, replacepos-15-10);
|
||||
p += replacepos-15-10;
|
||||
|
||||
/* copy the cleartext */
|
||||
s = cleartext;
|
||||
if (*s != '(' && s[1] != '(')
|
||||
return GNUPG_Bug; /*we already checked this */
|
||||
s += 2;
|
||||
startpos = s;
|
||||
while ( *s == '(' )
|
||||
{
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
goto invalid_sexp;
|
||||
s += n;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
goto invalid_sexp;
|
||||
s += n;
|
||||
if ( *s != ')' )
|
||||
goto invalid_sexp;
|
||||
s++;
|
||||
}
|
||||
if ( *s != ')' )
|
||||
goto invalid_sexp;
|
||||
endpos = s;
|
||||
s++;
|
||||
/* short intermezzo: Get the MIC */
|
||||
if (*s != '(')
|
||||
goto invalid_sexp;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!smatch (&s, n, "hash"))
|
||||
goto invalid_sexp;
|
||||
n = snext (&s);
|
||||
if (!smatch (&s, n, "sha1"))
|
||||
goto invalid_sexp;
|
||||
n = snext (&s);
|
||||
if (n != 20)
|
||||
goto invalid_sexp;
|
||||
memcpy (sha1hash, s, 20);
|
||||
s += n;
|
||||
if (*s != ')')
|
||||
goto invalid_sexp;
|
||||
/* end intermezzo */
|
||||
|
||||
/* append the parameter list */
|
||||
memcpy (p, startpos, endpos - startpos);
|
||||
p += endpos - startpos;
|
||||
|
||||
/* skip overt the protected list element in the original list */
|
||||
s = protectedkey + replacepos;
|
||||
assert (*s == '(');
|
||||
s++;
|
||||
i = 1;
|
||||
rc = sskip (&s, &i);
|
||||
if (rc)
|
||||
goto failure;
|
||||
startpos = s;
|
||||
i = 2; /* we are inside this level */
|
||||
rc = sskip (&s, &i);
|
||||
if (rc)
|
||||
goto failure;
|
||||
assert (s[-1] == ')');
|
||||
endpos = s; /* one behind the end of the list */
|
||||
|
||||
/* append the rest */
|
||||
memcpy (p, startpos, endpos - startpos);
|
||||
p += endpos - startpos;
|
||||
|
||||
/* ready */
|
||||
*result = newlist;
|
||||
return 0;
|
||||
|
||||
failure:
|
||||
xfree (newlist);
|
||||
return rc;
|
||||
|
||||
invalid_sexp:
|
||||
xfree (newlist);
|
||||
return GNUPG_Invalid_Sexp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Unprotect the key encoded in canonical format. We assume a valid
|
||||
S-Exp here. */
|
||||
int
|
||||
agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
|
||||
unsigned char **result, size_t *resultlen)
|
||||
{
|
||||
int rc;
|
||||
const unsigned char *s;
|
||||
size_t n;
|
||||
int infidx, i;
|
||||
unsigned char sha1hash[20], sha1hash2[20];
|
||||
const unsigned char *s2ksalt;
|
||||
unsigned long s2kcount;
|
||||
const unsigned char *iv;
|
||||
const unsigned char *prot_begin;
|
||||
unsigned char *cleartext;
|
||||
unsigned char *final;
|
||||
|
||||
s = protectedkey;
|
||||
if (*s != '(')
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
if (!smatch (&s, n, "protected-private-key"))
|
||||
return GNUPG_Unknown_Sexp;
|
||||
if (*s != '(')
|
||||
return GNUPG_Unknown_Sexp;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
|
||||
for (infidx=0; protect_info[infidx].algo
|
||||
&& !smatch (&s, n, protect_info[infidx].algo); infidx++)
|
||||
;
|
||||
if (!protect_info[infidx].algo)
|
||||
return GNUPG_Unsupported_Algorithm;
|
||||
|
||||
/* now find the list with the protected information. Here is an
|
||||
example for such a list:
|
||||
(protected openpgp-s2k3-sha1-aes-cbc
|
||||
((sha1 <salt> <count>) <Initialization_Vector>)
|
||||
<encrypted_data>)
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
if (*s != '(')
|
||||
return GNUPG_Invalid_Sexp;
|
||||
prot_begin = s;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
if (smatch (&s, n, "protected"))
|
||||
break;
|
||||
s += n;
|
||||
i = 1;
|
||||
rc = sskip (&s, &i);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
/* found */
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
if (!smatch (&s, n, "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc"))
|
||||
return GNUPG_Unsupported_Protection;
|
||||
if (*s != '(' || s[1] != '(')
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s += 2;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
if (!smatch (&s, n, "sha1"))
|
||||
return GNUPG_Unsupported_Protection;
|
||||
n = snext (&s);
|
||||
if (n != 8)
|
||||
return GNUPG_Corrupted_Protection;
|
||||
s2ksalt = s;
|
||||
s += n;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Corrupted_Protection;
|
||||
/* We expect a list close as next, so we can simply use strtoul()
|
||||
here. We might want to check that we only have digits - but this
|
||||
is nothing we should worry about */
|
||||
if (s[n] != ')' )
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s2kcount = strtoul (s, NULL, 10);
|
||||
if (!s2kcount)
|
||||
return GNUPG_Corrupted_Protection;
|
||||
s += n;
|
||||
s++; /* skip list end */
|
||||
|
||||
n = snext (&s);
|
||||
if (n != 16) /* Wrong blocksize for IV (we support ony aes-128) */
|
||||
return GNUPG_Corrupted_Protection;
|
||||
iv = s;
|
||||
s += n;
|
||||
if (*s != ')' )
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
|
||||
rc = do_decryption (s, n,
|
||||
passphrase, s2ksalt, s2kcount,
|
||||
iv, 16,
|
||||
&cleartext);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = merge_lists (protectedkey, prot_begin-protectedkey, cleartext,
|
||||
sha1hash, &final);
|
||||
xfree (cleartext);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = calculate_mic (final, sha1hash2);
|
||||
if (!rc && memcmp (sha1hash, sha1hash2, 20))
|
||||
rc = GNUPG_Corrupted_Protection;
|
||||
if (rc)
|
||||
{
|
||||
xfree (final);
|
||||
return rc;
|
||||
}
|
||||
|
||||
*result = final;
|
||||
*resultlen = gcry_sexp_canon_len (final, 0, NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check the type of the private key, this is one of the constants:
|
||||
PRIVATE_KEY_UNKNOWN if we can't figure out the type (this is the
|
||||
value 0), PRIVATE_KEY_CLEAR for an unprotected private key.
|
||||
PRIVATE_KEY_PROTECTED for an protected private key or
|
||||
PRIVATE_KEY_SHADOWED for a sub key where the secret parts are stored
|
||||
elsewhere. */
|
||||
int
|
||||
agent_private_key_type (const unsigned char *privatekey)
|
||||
{
|
||||
const unsigned char *s;
|
||||
size_t n;
|
||||
|
||||
s = privatekey;
|
||||
if (*s != '(')
|
||||
return PRIVATE_KEY_UNKNOWN;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return PRIVATE_KEY_UNKNOWN;
|
||||
if (smatch (&s, n, "protected-private-key"))
|
||||
return PRIVATE_KEY_PROTECTED;
|
||||
if (smatch (&s, n, "shadowed-private-key"))
|
||||
return PRIVATE_KEY_SHADOWED;
|
||||
if (smatch (&s, n, "private-key"))
|
||||
return PRIVATE_KEY_CLEAR;
|
||||
return PRIVATE_KEY_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Transform a passphrase into a suitable key of length KEYLEN and
|
||||
store this key in the caller provided buffer KEY. The caller must
|
||||
provide an HASHALGO, a valid S2KMODE (see rfc-2440) and depending on
|
||||
that mode an S2KSALT of 8 random bytes and an S2KCOUNT (a suitable
|
||||
value is 96).
|
||||
|
||||
Returns an error code on failure. */
|
||||
static int
|
||||
hash_passphrase (const char *passphrase, int hashalgo,
|
||||
int s2kmode,
|
||||
const unsigned char *s2ksalt,
|
||||
unsigned long s2kcount,
|
||||
unsigned char *key, size_t keylen)
|
||||
{
|
||||
GCRY_MD_HD md;
|
||||
int pass, i;
|
||||
int used = 0;
|
||||
int pwlen = strlen (passphrase);
|
||||
|
||||
if ( (s2kmode != 0 && s2kmode != 1 && s2kmode != 3)
|
||||
|| !hashalgo || !keylen || !key || !passphrase)
|
||||
return GNUPG_Invalid_Value;
|
||||
if ((s2kmode == 1 ||s2kmode == 3) && !s2ksalt)
|
||||
return GNUPG_Invalid_Value;
|
||||
|
||||
md = gcry_md_open (hashalgo, GCRY_MD_FLAG_SECURE);
|
||||
if (!md)
|
||||
return map_gcry_err (gcry_errno());
|
||||
|
||||
for (pass=0; used < keylen; pass++)
|
||||
{
|
||||
if (pass)
|
||||
{
|
||||
gcry_md_reset (md);
|
||||
for (i=0; i < pass; i++) /* preset the hash context */
|
||||
gcry_md_putc (md, 0);
|
||||
}
|
||||
|
||||
if (s2kmode == 1 || s2kmode == 3)
|
||||
{
|
||||
int len2 = pwlen + 8;
|
||||
unsigned long count = len2;
|
||||
|
||||
if (s2kmode == 3)
|
||||
{
|
||||
count = (16ul + (s2kcount & 15)) << ((s2kcount >> 4) + 6);
|
||||
if (count < len2)
|
||||
count = len2;
|
||||
}
|
||||
|
||||
while (count > len2)
|
||||
{
|
||||
gcry_md_write (md, s2ksalt, 8);
|
||||
gcry_md_write (md, passphrase, pwlen);
|
||||
count -= len2;
|
||||
}
|
||||
if (count < 8)
|
||||
gcry_md_write (md, s2ksalt, count);
|
||||
else
|
||||
{
|
||||
gcry_md_write (md, s2ksalt, 8);
|
||||
count -= 8;
|
||||
gcry_md_write (md, passphrase, count);
|
||||
}
|
||||
}
|
||||
else
|
||||
gcry_md_write (md, passphrase, pwlen);
|
||||
|
||||
gcry_md_final (md);
|
||||
i = gcry_md_get_algo_dlen (hashalgo);
|
||||
if (i > keylen - used)
|
||||
i = keylen - used;
|
||||
memcpy (key+used, gcry_md_read (md, hashalgo), i);
|
||||
used += i;
|
||||
}
|
||||
gcry_md_close(md);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Create a shadow key from a public key. We use the shadow protocol
|
||||
"ti-v1" and insert the S-expressionn SHADOW_INFO. The resulting
|
||||
S-expression is returned in an allocated buffer RESULT will point
|
||||
to. The input parameters are expected to be valid canonilized
|
||||
S-expressions */
|
||||
int
|
||||
agent_shadow_key (const unsigned char *pubkey,
|
||||
const unsigned char *shadow_info,
|
||||
unsigned char **result)
|
||||
{
|
||||
const unsigned char *s;
|
||||
const unsigned char *point;
|
||||
size_t n;
|
||||
int depth = 0;
|
||||
unsigned char *p;
|
||||
size_t pubkey_len = gcry_sexp_canon_len (pubkey, 0, NULL,NULL);
|
||||
size_t shadow_info_len = gcry_sexp_canon_len (shadow_info, 0, NULL,NULL);
|
||||
|
||||
if (!pubkey_len || !shadow_info_len)
|
||||
return GNUPG_Invalid_Value;
|
||||
s = pubkey;
|
||||
if (*s != '(')
|
||||
return GNUPG_Invalid_Sexp;
|
||||
depth++;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
if (!smatch (&s, n, "public-key"))
|
||||
return GNUPG_Unknown_Sexp;
|
||||
if (*s != '(')
|
||||
return GNUPG_Unknown_Sexp;
|
||||
depth++;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s += n; /* skip over the algorithm name */
|
||||
|
||||
while (*s != ')')
|
||||
{
|
||||
if (*s != '(')
|
||||
return GNUPG_Invalid_Sexp;
|
||||
depth++;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s += n;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s +=n; /* skip value */
|
||||
if (*s != ')')
|
||||
return GNUPG_Invalid_Sexp;
|
||||
depth--;
|
||||
s++;
|
||||
}
|
||||
point = s; /* insert right before the point */
|
||||
depth--;
|
||||
s++;
|
||||
assert (depth == 1);
|
||||
|
||||
/* calculate required length by taking in account: the "shadowed-"
|
||||
prefix, the "shadowed", "t1-v1" as well as some parenthesis */
|
||||
n = 12 + pubkey_len + 1 + 3+8 + 2+5 + shadow_info_len + 1;
|
||||
*result = p = xtrymalloc (n);
|
||||
if (!p)
|
||||
return GNUPG_Out_Of_Core;
|
||||
p = stpcpy (p, "(20:shadowed-private-key");
|
||||
/* (10:public-key ...)*/
|
||||
memcpy (p, pubkey+14, point - (pubkey+14));
|
||||
p += point - (pubkey+14);
|
||||
p = stpcpy (p, "(8:shadowed5:t1-v1");
|
||||
memcpy (p, shadow_info, shadow_info_len);
|
||||
p += shadow_info_len;
|
||||
*p++ = ')';
|
||||
memcpy (p, point, pubkey_len - (point - pubkey));
|
||||
p += pubkey_len - (point - pubkey);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse a canonical encoded shadowed key and return a pointer to the
|
||||
inner list with the shadow_info */
|
||||
int
|
||||
agent_get_shadow_info (const unsigned char *shadowkey,
|
||||
unsigned char const **shadow_info)
|
||||
{
|
||||
const unsigned char *s;
|
||||
size_t n;
|
||||
int depth = 0;
|
||||
|
||||
s = shadowkey;
|
||||
if (*s != '(')
|
||||
return GNUPG_Invalid_Sexp;
|
||||
depth++;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
if (!smatch (&s, n, "shadowed-private-key"))
|
||||
return GNUPG_Unknown_Sexp;
|
||||
if (*s != '(')
|
||||
return GNUPG_Unknown_Sexp;
|
||||
depth++;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s += n; /* skip over the algorithm name */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (*s == ')')
|
||||
return GNUPG_Unknown_Sexp;
|
||||
if (*s != '(')
|
||||
return GNUPG_Invalid_Sexp;
|
||||
depth++;
|
||||
s++;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
if (smatch (&s, n, "shadowed"))
|
||||
break;
|
||||
s += n;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s +=n; /* skip value */
|
||||
if (*s != ')')
|
||||
return GNUPG_Invalid_Sexp;
|
||||
depth--;
|
||||
s++;
|
||||
}
|
||||
/* found the shadowed list, s points to the protocol */
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
if (smatch (&s, n, "t1-v1"))
|
||||
{
|
||||
if (*s != '(')
|
||||
return GNUPG_Invalid_Sexp;
|
||||
*shadow_info = s;
|
||||
}
|
||||
else
|
||||
return GNUPG_Unsupported_Protocol;
|
||||
return 0;
|
||||
}
|
||||
|
460
agent/query.c
460
agent/query.c
@ -1,460 +0,0 @@
|
||||
/* query.c - fork of the pinentry to query stuff from the user
|
||||
* Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef USE_GNU_PTH
|
||||
# include <pth.h>
|
||||
#endif
|
||||
|
||||
#include "agent.h"
|
||||
#include "i18n.h"
|
||||
#include "../assuan/assuan.h"
|
||||
|
||||
#ifdef _POSIX_OPEN_MAX
|
||||
#define MAX_OPEN_FDS _POSIX_OPEN_MAX
|
||||
#else
|
||||
#define MAX_OPEN_FDS 20
|
||||
#endif
|
||||
|
||||
static ASSUAN_CONTEXT entry_ctx = NULL;
|
||||
#ifdef USE_GNU_PTH
|
||||
static pth_mutex_t entry_lock = PTH_MUTEX_INIT;
|
||||
#endif
|
||||
|
||||
/* data to be passed to our callbacks */
|
||||
struct entry_parm_s {
|
||||
int lines;
|
||||
size_t size;
|
||||
char *buffer;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
static int
|
||||
unlock_pinentry (int rc)
|
||||
{
|
||||
#ifdef USE_GNU_PTH
|
||||
if (!pth_mutex_release (&entry_lock))
|
||||
{
|
||||
log_error ("failed to release the entry lock\n");
|
||||
if (!rc)
|
||||
rc = GNUPG_Internal_Error;
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Fork off the pin entry if this has not already been done. Note,
|
||||
that this function must always be used to aquire the lock for the
|
||||
pinentry - we will serialize _all_ pinentry calls.
|
||||
*/
|
||||
static int
|
||||
start_pinentry (void)
|
||||
{
|
||||
int rc;
|
||||
const char *pgmname;
|
||||
ASSUAN_CONTEXT ctx;
|
||||
const char *argv[5];
|
||||
int no_close_list[3];
|
||||
int i;
|
||||
|
||||
#ifdef USE_GNU_PTH
|
||||
if (!pth_mutex_acquire (&entry_lock, 0, NULL))
|
||||
{
|
||||
log_error ("failed to acquire the entry lock\n");
|
||||
return GNUPG_Internal_Error;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (entry_ctx)
|
||||
return 0;
|
||||
|
||||
if (opt.verbose)
|
||||
log_info ("no running PIN Entry - starting it\n");
|
||||
|
||||
if (fflush (NULL))
|
||||
{
|
||||
log_error ("error flushing pending output: %s\n", strerror (errno));
|
||||
return unlock_pinentry (seterr (Write_Error));
|
||||
}
|
||||
|
||||
if (!opt.pinentry_program || !*opt.pinentry_program)
|
||||
opt.pinentry_program = GNUPG_DEFAULT_PINENTRY;
|
||||
if ( !(pgmname = strrchr (opt.pinentry_program, '/')))
|
||||
pgmname = opt.pinentry_program;
|
||||
else
|
||||
pgmname++;
|
||||
|
||||
/* FIXME: We must do this thread specific */
|
||||
argv[0] = pgmname;
|
||||
if (opt.display && !opt.keep_display)
|
||||
{
|
||||
argv[1] = "--display";
|
||||
argv[2] = opt.display;
|
||||
argv[3] = NULL;
|
||||
}
|
||||
else
|
||||
argv[1] = NULL;
|
||||
|
||||
i=0;
|
||||
if (!opt.running_detached)
|
||||
{
|
||||
if (log_get_fd () != -1)
|
||||
no_close_list[i++] = log_get_fd ();
|
||||
no_close_list[i++] = fileno (stderr);
|
||||
}
|
||||
no_close_list[i] = -1;
|
||||
|
||||
/* connect to the pinentry and perform initial handshaking */
|
||||
rc = assuan_pipe_connect (&ctx, opt.pinentry_program, (char**)argv,
|
||||
no_close_list);
|
||||
if (rc)
|
||||
{
|
||||
log_error ("can't connect to the PIN entry module: %s\n",
|
||||
assuan_strerror (rc));
|
||||
return unlock_pinentry (seterr (No_PIN_Entry));
|
||||
}
|
||||
entry_ctx = ctx;
|
||||
|
||||
if (DBG_ASSUAN)
|
||||
log_debug ("connection to PIN entry established\n");
|
||||
|
||||
rc = assuan_transact (entry_ctx,
|
||||
opt.no_grab? "OPTION no-grab":"OPTION grab",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
if (opt.ttyname && !opt.keep_tty)
|
||||
{
|
||||
char *optstr;
|
||||
if (asprintf (&optstr, "OPTION ttyname=%s", opt.ttyname) < 0 )
|
||||
return unlock_pinentry (GNUPG_Out_Of_Core);
|
||||
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL);
|
||||
free (optstr);
|
||||
if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
}
|
||||
if (opt.ttytype && !opt.keep_tty)
|
||||
{
|
||||
char *optstr;
|
||||
if (asprintf (&optstr, "OPTION ttytype=%s", opt.ttytype) < 0 )
|
||||
return unlock_pinentry (GNUPG_Out_Of_Core);
|
||||
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL);
|
||||
if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
}
|
||||
if (opt.lc_ctype)
|
||||
{
|
||||
char *optstr;
|
||||
if (asprintf (&optstr, "OPTION lc-ctype=%s", opt.lc_ctype) < 0 )
|
||||
return unlock_pinentry (GNUPG_Out_Of_Core);
|
||||
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL);
|
||||
if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
}
|
||||
if (opt.lc_messages)
|
||||
{
|
||||
char *optstr;
|
||||
if (asprintf (&optstr, "OPTION lc-messages=%s", opt.lc_messages) < 0 )
|
||||
return unlock_pinentry (GNUPG_Out_Of_Core);
|
||||
rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL);
|
||||
if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static AssuanError
|
||||
getpin_cb (void *opaque, const void *buffer, size_t length)
|
||||
{
|
||||
struct entry_parm_s *parm = opaque;
|
||||
|
||||
if (!buffer)
|
||||
return 0;
|
||||
|
||||
/* we expect the pin to fit on one line */
|
||||
if (parm->lines || length >= parm->size)
|
||||
return ASSUAN_Too_Much_Data;
|
||||
|
||||
/* fixme: we should make sure that the assuan buffer is allocated in
|
||||
secure memory or read the response byte by byte */
|
||||
memcpy (parm->buffer, buffer, length);
|
||||
parm->buffer[length] = 0;
|
||||
parm->lines++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
all_digitsp( const char *s)
|
||||
{
|
||||
for (; *s && *s >= '0' && *s <= '9'; s++)
|
||||
;
|
||||
return !*s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Call the Entry and ask for the PIN. We do check for a valid PIN
|
||||
number here and repeat it as long as we have invalid formed
|
||||
numbers. */
|
||||
int
|
||||
agent_askpin (const char *desc_text, struct pin_entry_info_s *pininfo)
|
||||
{
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct entry_parm_s parm;
|
||||
const char *errtext = NULL;
|
||||
int is_pin = 0;
|
||||
|
||||
if (opt.batch)
|
||||
return 0; /* fixme: we should return BAD PIN */
|
||||
|
||||
if (!pininfo || pininfo->max_length < 1)
|
||||
return seterr (Invalid_Value);
|
||||
if (!desc_text && pininfo->min_digits)
|
||||
desc_text = _("Please enter your PIN, so that the secret key "
|
||||
"can be unlocked for this session");
|
||||
else if (!desc_text)
|
||||
desc_text = _("Please enter your passphrase, so that the secret key "
|
||||
"can be unlocked for this session");
|
||||
|
||||
is_pin = desc_text && strstr (desc_text, "PIN");
|
||||
|
||||
rc = start_pinentry ();
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
snprintf (line, DIM(line)-1, "SETDESC %s", desc_text);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
|
||||
rc = assuan_transact (entry_ctx,
|
||||
is_pin? "SETPROMPT PIN:"
|
||||
: "SETPROMPT Passphrase:",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
|
||||
for (;pininfo->failed_tries < pininfo->max_tries; pininfo->failed_tries++)
|
||||
{
|
||||
memset (&parm, 0, sizeof parm);
|
||||
parm.size = pininfo->max_length;
|
||||
parm.buffer = pininfo->pin;
|
||||
|
||||
if (errtext)
|
||||
{
|
||||
/* fixme: should we show the try count? It must be translated */
|
||||
snprintf (line, DIM(line)-1, "SETERROR %s (try %d of %d)",
|
||||
errtext, pininfo->failed_tries+1, pininfo->max_tries);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
errtext = NULL;
|
||||
}
|
||||
|
||||
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
|
||||
NULL, NULL, NULL, NULL);
|
||||
if (rc == ASSUAN_Too_Much_Data)
|
||||
errtext = is_pin? _("PIN too long")
|
||||
: _("Passphrase too long");
|
||||
else if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
|
||||
if (!errtext && pininfo->min_digits)
|
||||
{
|
||||
/* do some basic checks on the entered PIN. */
|
||||
if (!all_digitsp (pininfo->pin))
|
||||
errtext = _("Invalid characters in PIN");
|
||||
else if (pininfo->max_digits
|
||||
&& strlen (pininfo->pin) > pininfo->max_digits)
|
||||
errtext = _("PIN too long");
|
||||
else if (strlen (pininfo->pin) < pininfo->min_digits)
|
||||
errtext = _("PIN too short");
|
||||
}
|
||||
|
||||
if (!errtext && pininfo->check_cb)
|
||||
{
|
||||
/* More checks by utilizing the optional callback. */
|
||||
pininfo->cb_errtext = NULL;
|
||||
rc = pininfo->check_cb (pininfo);
|
||||
if (rc == -1 && pininfo->cb_errtext)
|
||||
errtext = pininfo->cb_errtext;
|
||||
else if (rc == GNUPG_Bad_Passphrase || rc == GNUPG_Bad_PIN)
|
||||
errtext = (is_pin? _("Bad PIN")
|
||||
: _("Bad Passphrase"));
|
||||
else if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
}
|
||||
|
||||
if (!errtext)
|
||||
return unlock_pinentry (0); /* okay, got a PIN or passphrase */
|
||||
}
|
||||
|
||||
return unlock_pinentry (pininfo->min_digits? GNUPG_Bad_PIN
|
||||
: GNUPG_Bad_Passphrase);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Ask for the passphrase using the supplied arguments. The
|
||||
passphrase is returned in RETPASS as an hex encoded string to be
|
||||
freed by the caller */
|
||||
int
|
||||
agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
|
||||
const char *errtext)
|
||||
{
|
||||
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct entry_parm_s parm;
|
||||
unsigned char *p, *hexstring;
|
||||
int i;
|
||||
|
||||
*retpass = NULL;
|
||||
if (opt.batch)
|
||||
return GNUPG_Bad_Passphrase;
|
||||
|
||||
rc = start_pinentry ();
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (!prompt)
|
||||
prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");
|
||||
|
||||
|
||||
if (desc)
|
||||
snprintf (line, DIM(line)-1, "SETDESC %s", desc);
|
||||
else
|
||||
snprintf (line, DIM(line)-1, "RESET");
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
|
||||
snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
|
||||
if (errtext)
|
||||
{
|
||||
snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
}
|
||||
|
||||
memset (&parm, 0, sizeof parm);
|
||||
parm.size = ASSUAN_LINELENGTH/2 - 5;
|
||||
parm.buffer = gcry_malloc_secure (parm.size+10);
|
||||
if (!parm.buffer)
|
||||
return unlock_pinentry (seterr (Out_Of_Core));
|
||||
|
||||
assuan_begin_confidential (entry_ctx);
|
||||
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
{
|
||||
xfree (parm.buffer);
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
}
|
||||
|
||||
hexstring = gcry_malloc_secure (strlen (parm.buffer)*2+1);
|
||||
if (!hexstring)
|
||||
{
|
||||
xfree (parm.buffer);
|
||||
return unlock_pinentry (seterr (Out_Of_Core));
|
||||
}
|
||||
|
||||
for (i=0, p=parm.buffer; *p; p++, i += 2)
|
||||
sprintf (hexstring+i, "%02X", *p);
|
||||
|
||||
xfree (parm.buffer);
|
||||
*retpass = hexstring;
|
||||
return unlock_pinentry (0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Pop up the PIN-entry, display the text and the prompt and ask the
|
||||
user to confirm this. We return 0 for success, ie. the used
|
||||
confirmed it, GNUPG_Not_Confirmed for what the text says or an
|
||||
other error. */
|
||||
int
|
||||
agent_get_confirmation (const char *desc, const char *ok, const char *cancel)
|
||||
{
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
|
||||
rc = start_pinentry ();
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (desc)
|
||||
snprintf (line, DIM(line)-1, "SETDESC %s", desc);
|
||||
else
|
||||
snprintf (line, DIM(line)-1, "RESET");
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
|
||||
if (ok)
|
||||
{
|
||||
snprintf (line, DIM(line)-1, "SETOK %s", ok);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
}
|
||||
if (cancel)
|
||||
{
|
||||
snprintf (line, DIM(line)-1, "SETCANCEL %s", cancel);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
}
|
||||
|
||||
rc = assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
return unlock_pinentry (map_assuan_err (rc));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,98 +0,0 @@
|
||||
/* sexp-parse.h - S-Exp helper functions
|
||||
* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#ifndef SEXP_PARSE_H
|
||||
#define SEXP_PARSE_H
|
||||
|
||||
#include "../common/util.h"
|
||||
|
||||
/* Return the length of the next S-Exp part and update the pointer to
|
||||
the first data byte. 0 is return on error */
|
||||
static inline size_t
|
||||
snext (unsigned char const **buf)
|
||||
{
|
||||
const unsigned char *s;
|
||||
int n;
|
||||
|
||||
s = *buf;
|
||||
for (n=0; *s && *s != ':' && digitp (s); s++)
|
||||
n = n*10 + atoi_1 (s);
|
||||
if (!n || *s != ':')
|
||||
return 0; /* we don't allow empty lengths */
|
||||
*buf = s+1;
|
||||
return n;
|
||||
}
|
||||
|
||||
/* Skip over the S-Expression BUF points to and update BUF to point to
|
||||
the chacter right behind. DEPTH gives the initial number of open
|
||||
lists and may be passed as a positive number to skip over the
|
||||
remainder of an S-Expression if the current position is somewhere
|
||||
in an S-Expression. The function may return an error code if it
|
||||
encounters an impossible conditions */
|
||||
static inline int
|
||||
sskip (unsigned char const **buf, int *depth)
|
||||
{
|
||||
const unsigned char *s = *buf;
|
||||
size_t n;
|
||||
int d = *depth;
|
||||
|
||||
while (d > 0)
|
||||
{
|
||||
if (*s == '(')
|
||||
{
|
||||
d++;
|
||||
s++;
|
||||
}
|
||||
else if (*s == ')')
|
||||
{
|
||||
d--;
|
||||
s++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!d)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
n = snext (&s);
|
||||
if (!n)
|
||||
return GNUPG_Invalid_Sexp;
|
||||
s += n;
|
||||
}
|
||||
}
|
||||
*buf = s;
|
||||
*depth = d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Check whether the the string at the address BUF points to matches
|
||||
the token. Return true on match and update BUF to point behind the
|
||||
token. */
|
||||
static inline int
|
||||
smatch (unsigned char const **buf, size_t buflen, const char *token)
|
||||
{
|
||||
size_t toklen = strlen (token);
|
||||
|
||||
if (buflen != toklen || memcmp (*buf, token, toklen))
|
||||
return 0;
|
||||
*buf += toklen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /*SEXP_PARSE_H*/
|
@ -1,485 +0,0 @@
|
||||
/* simple-pwquery.c - A simple password query cleint for gpg-agent
|
||||
* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
/* This module is intended as a standalone client implementation to
|
||||
gpg-agent's GET_PASSPHRASE command. In particular it does not use
|
||||
the Assuan library and can only cope with an already running
|
||||
gpg-agent. Some stuff is configurable in the header file. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
#define SIMPLE_PWQUERY_IMPLEMENTATION 1
|
||||
#include "simple-pwquery.h"
|
||||
|
||||
#if defined(SPWQ_USE_LOGGING) && !defined(HAVE_JNLIB_LOGGING)
|
||||
# undef SPWQ_USE_LOGGING
|
||||
#endif
|
||||
|
||||
#ifndef _
|
||||
#define _(a) (a)
|
||||
#endif
|
||||
|
||||
#if !defined (hexdigitp) && !defined (xtoi_2)
|
||||
#define digitp(p) (*(p) >= '0' && *(p) <= '9')
|
||||
#define hexdigitp(a) (digitp (a) \
|
||||
|| (*(a) >= 'A' && *(a) <= 'F') \
|
||||
|| (*(a) >= 'a' && *(a) <= 'f'))
|
||||
#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
|
||||
*(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
|
||||
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
|
||||
#endif
|
||||
|
||||
|
||||
/* Write NBYTES of BUF to file descriptor FD. */
|
||||
static int
|
||||
writen (int fd, const void *buf, size_t nbytes)
|
||||
{
|
||||
size_t nleft = nbytes;
|
||||
int nwritten;
|
||||
|
||||
while (nleft > 0)
|
||||
{
|
||||
nwritten = write( fd, buf, nleft );
|
||||
if (nwritten < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
nwritten = 0;
|
||||
else {
|
||||
#ifdef SPWQ_USE_LOGGING
|
||||
log_error ("write failed: %s\n", strerror (errno));
|
||||
#endif
|
||||
return SPWQ_IO_ERROR;
|
||||
}
|
||||
}
|
||||
nleft -= nwritten;
|
||||
buf = (const char*)buf + nwritten;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Read an entire line and return number of bytes read. */
|
||||
static int
|
||||
readline (int fd, char *buf, size_t buflen)
|
||||
{
|
||||
size_t nleft = buflen;
|
||||
char *p;
|
||||
int nread = 0;
|
||||
|
||||
while (nleft > 0)
|
||||
{
|
||||
int n = read (fd, buf, nleft);
|
||||
if (n < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return -(SPWQ_IO_ERROR);
|
||||
}
|
||||
else if (!n)
|
||||
{
|
||||
return -(SPWQ_PROTOCOL_ERROR); /* incomplete line */
|
||||
}
|
||||
p = buf;
|
||||
nleft -= n;
|
||||
buf += n;
|
||||
nread += n;
|
||||
|
||||
for (; n && *p != '\n'; n--, p++)
|
||||
;
|
||||
if (n)
|
||||
{
|
||||
break; /* at least one full line available - that's enough.
|
||||
This function is just a simple implementation, so
|
||||
it is okay to forget about pending bytes */
|
||||
}
|
||||
}
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
|
||||
/* Send an option to the agent */
|
||||
static int
|
||||
agent_send_option (int fd, const char *name, const char *value)
|
||||
{
|
||||
char buf[200];
|
||||
int nread;
|
||||
char *line;
|
||||
int i;
|
||||
|
||||
line = spwq_malloc (7 + strlen (name) + 1 + strlen (value) + 2);
|
||||
if (!line)
|
||||
return SPWQ_OUT_OF_CORE;
|
||||
strcpy (stpcpy (stpcpy (stpcpy (
|
||||
stpcpy (line, "OPTION "), name), "="), value), "\n");
|
||||
i = writen (fd, line, strlen (line));
|
||||
spwq_free (line);
|
||||
if (i)
|
||||
return i;
|
||||
|
||||
/* get response */
|
||||
nread = readline (fd, buf, DIM(buf)-1);
|
||||
if (nread < 0)
|
||||
return -nread;
|
||||
if (nread < 3)
|
||||
return SPWQ_PROTOCOL_ERROR;
|
||||
|
||||
if (buf[0] == 'O' && buf[1] == 'K' && (buf[2] == ' ' || buf[2] == '\n'))
|
||||
return 0; /* okay */
|
||||
|
||||
return SPWQ_ERR_RESPONSE;
|
||||
}
|
||||
|
||||
|
||||
/* Send all available options to the agent. */
|
||||
static int
|
||||
agent_send_all_options (int fd)
|
||||
{
|
||||
char *dft_display = NULL;
|
||||
char *dft_ttyname = NULL;
|
||||
char *dft_ttytype = NULL;
|
||||
int rc = 0;
|
||||
|
||||
dft_display = getenv ("DISPLAY");
|
||||
if (dft_display)
|
||||
{
|
||||
if ((rc = agent_send_option (fd, "display", dft_display)))
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (ttyname (1))
|
||||
dft_ttyname = ttyname (1);
|
||||
if (dft_ttyname)
|
||||
{
|
||||
if ((rc=agent_send_option (fd, "ttyname", dft_ttyname)))
|
||||
return rc;
|
||||
}
|
||||
|
||||
dft_ttytype = getenv ("TERM");
|
||||
if (dft_ttyname && dft_ttytype)
|
||||
{
|
||||
if ((rc = agent_send_option (fd, "ttytype", dft_ttytype)))
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if defined(HAVE_SETLOCALE)
|
||||
{
|
||||
char *old_lc = NULL;
|
||||
char *dft_lc = NULL;
|
||||
|
||||
#if defined(LC_CTYPE)
|
||||
old_lc = setlocale (LC_CTYPE, NULL);
|
||||
if (old_lc)
|
||||
{
|
||||
char *p = spwq_malloc (strlen (old_lc)+1);
|
||||
if (!p)
|
||||
return SPWQ_OUT_OF_CORE;
|
||||
strcpy (p, old_lc);
|
||||
old_lc = p;
|
||||
}
|
||||
dft_lc = setlocale (LC_CTYPE, "");
|
||||
if (dft_ttyname && dft_lc)
|
||||
rc = agent_send_option (fd, "lc-ctype", dft_lc);
|
||||
if (old_lc)
|
||||
{
|
||||
setlocale (LC_CTYPE, old_lc);
|
||||
spwq_free (old_lc);
|
||||
}
|
||||
if (rc)
|
||||
return rc;
|
||||
#endif
|
||||
|
||||
#if defined(LC_MESSAGES)
|
||||
old_lc = setlocale (LC_MESSAGES, NULL);
|
||||
if (old_lc)
|
||||
{
|
||||
char *p = spwq_malloc (strlen (old_lc)+1);
|
||||
if (!p)
|
||||
return SPWQ_OUT_OF_CORE;
|
||||
strcpy (p, old_lc);
|
||||
old_lc = p;
|
||||
}
|
||||
dft_lc = setlocale (LC_MESSAGES, "");
|
||||
if (dft_ttyname && dft_lc)
|
||||
rc = agent_send_option (fd, "lc-messages", dft_lc);
|
||||
if (old_lc)
|
||||
{
|
||||
setlocale (LC_MESSAGES, old_lc);
|
||||
spwq_free (old_lc);
|
||||
}
|
||||
if (rc)
|
||||
return rc;
|
||||
#endif
|
||||
}
|
||||
#endif /*HAVE_SETLOCALE*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Try to open a connection to the agent, send all options and return
|
||||
the file descriptor for the connection. Return -1 in case of
|
||||
error. */
|
||||
static int
|
||||
agent_open (int *rfd)
|
||||
{
|
||||
int rc;
|
||||
int fd;
|
||||
char *infostr, *p;
|
||||
struct sockaddr_un client_addr;
|
||||
size_t len;
|
||||
int prot;
|
||||
char line[200];
|
||||
int nread;
|
||||
|
||||
*rfd = -1;
|
||||
infostr = getenv ( "GPG_AGENT_INFO" );
|
||||
if ( !infostr )
|
||||
{
|
||||
#ifdef SPWQ_USE_LOGGING
|
||||
log_error (_("gpg-agent is not available in this session\n"));
|
||||
#endif
|
||||
return SPWQ_NO_AGENT;
|
||||
}
|
||||
|
||||
if ( !(p = strchr ( infostr, ':')) || p == infostr
|
||||
|| (p-infostr)+1 >= sizeof client_addr.sun_path )
|
||||
{
|
||||
#ifdef SPWQ_USE_LOGGING
|
||||
log_error ( _("malformed GPG_AGENT_INFO environment variable\n"));
|
||||
#endif
|
||||
return SPWQ_NO_AGENT;
|
||||
}
|
||||
*p++ = 0;
|
||||
|
||||
while (*p && *p != ':')
|
||||
p++;
|
||||
prot = *p? atoi (p+1) : 0;
|
||||
if ( prot != 1)
|
||||
{
|
||||
#ifdef SPWQ_USE_LOGGING
|
||||
log_error (_("gpg-agent protocol version %d is not supported\n"),prot);
|
||||
#endif
|
||||
return SPWQ_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
if( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 )
|
||||
{
|
||||
#ifdef SPWQ_USE_LOGGING
|
||||
log_error ("can't create socket: %s\n", strerror(errno) );
|
||||
#endif
|
||||
return SPWQ_SYS_ERROR;
|
||||
}
|
||||
|
||||
memset (&client_addr, 0, sizeof client_addr);
|
||||
client_addr.sun_family = AF_UNIX;
|
||||
strcpy (client_addr.sun_path, infostr);
|
||||
len = (offsetof (struct sockaddr_un, sun_path)
|
||||
+ strlen(client_addr.sun_path) + 1);
|
||||
|
||||
if (connect (fd, (struct sockaddr*)&client_addr, len ) == -1)
|
||||
{
|
||||
#ifdef SPWQ_USE_LOGGING
|
||||
log_error ( _("can't connect to `%s': %s\n"), infostr, strerror (errno));
|
||||
#endif
|
||||
close (fd );
|
||||
return SPWQ_IO_ERROR;
|
||||
}
|
||||
|
||||
nread = readline (fd, line, DIM(line));
|
||||
if (nread < 3 || !(line[0] == 'O' && line[1] == 'K'
|
||||
&& (line[2] == '\n' || line[2] == ' ')) )
|
||||
{
|
||||
#ifdef SPWQ_USE_LOGGING
|
||||
log_error ( _("communication problem with gpg-agent\n"));
|
||||
#endif
|
||||
close (fd );
|
||||
return SPWQ_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
rc = agent_send_all_options (fd);
|
||||
if (rc)
|
||||
{
|
||||
#ifdef SPWQ_USE_LOGGING
|
||||
log_error (_("problem setting the gpg-agent options\n"));
|
||||
#endif
|
||||
close (fd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
*rfd = fd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Copy text to BUFFER and escape as required. Return a poiinter to
|
||||
the end of the new buffer. NOte that BUFFER must be large enough
|
||||
to keep the entire text; allocataing it 3 times the size of TEXT
|
||||
is sufficient. */
|
||||
static char *
|
||||
copy_and_escape (char *buffer, const char *text)
|
||||
{
|
||||
int i;
|
||||
char *p = buffer;
|
||||
|
||||
for (i=0; text[i]; i++)
|
||||
{
|
||||
if (text[i] < ' ' || text[i] == '+')
|
||||
{
|
||||
sprintf (p, "%%%02X", text[i]);
|
||||
p += 3;
|
||||
}
|
||||
else if (text[i] == ' ')
|
||||
*p++ = '+';
|
||||
else
|
||||
*p++ = text[i];
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/* Ask the gpg-agent for a passphrase and present the user with a
|
||||
DESCRIPTION, a PROMPT and optiaonlly with a TRYAGAIN extra text.
|
||||
If a CACHEID is not NULL it is used to locate the passphrase in in
|
||||
the cache and store it under this ID. If ERRORCODE is not NULL it
|
||||
should point a variable receiving an errorcode; thsi errocode might
|
||||
be 0 if the user canceled the operation. The function returns NULL
|
||||
to indicate an error. */
|
||||
char *
|
||||
simple_pwquery (const char *cacheid,
|
||||
const char *tryagain,
|
||||
const char *prompt,
|
||||
const char *description,
|
||||
int *errorcode)
|
||||
{
|
||||
int fd = -1;
|
||||
int nread;
|
||||
char *result = NULL;
|
||||
char *pw = NULL;
|
||||
char *p;
|
||||
int rc, i;
|
||||
|
||||
rc = agent_open (&fd);
|
||||
if (rc)
|
||||
goto leave;
|
||||
|
||||
if (!cacheid)
|
||||
cacheid = "X";
|
||||
if (!tryagain)
|
||||
tryagain = "X";
|
||||
if (!prompt)
|
||||
prompt = "X";
|
||||
if (!description)
|
||||
description = "X";
|
||||
|
||||
{
|
||||
char *line;
|
||||
/* We allocate 3 times the needed space so that there is enough
|
||||
space for escaping. */
|
||||
line = spwq_malloc (15
|
||||
+ 3*strlen (cacheid) + 1
|
||||
+ 3*strlen (tryagain) + 1
|
||||
+ 3*strlen (prompt) + 1
|
||||
+ 3*strlen (description) + 1
|
||||
+ 2);
|
||||
if (!line)
|
||||
{
|
||||
rc = SPWQ_OUT_OF_CORE;
|
||||
goto leave;
|
||||
}
|
||||
strcpy (line, "GET_PASSPHRASE ");
|
||||
p = line+15;
|
||||
p = copy_and_escape (p, cacheid);
|
||||
*p++ = ' ';
|
||||
p = copy_and_escape (p, tryagain);
|
||||
*p++ = ' ';
|
||||
p = copy_and_escape (p, prompt);
|
||||
*p++ = ' ';
|
||||
p = copy_and_escape (p, description);
|
||||
*p++ = '\n';
|
||||
rc = writen (fd, line, p - line);
|
||||
spwq_free (line);
|
||||
if (rc)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* get response */
|
||||
pw = spwq_secure_malloc (500);
|
||||
nread = readline (fd, pw, 499);
|
||||
if (nread < 0)
|
||||
{
|
||||
rc = -nread;
|
||||
goto leave;
|
||||
}
|
||||
if (nread < 3)
|
||||
{
|
||||
rc = SPWQ_PROTOCOL_ERROR;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
if (pw[0] == 'O' && pw[1] == 'K' && pw[2] == ' ')
|
||||
{ /* we got a passphrase - convert it back from hex */
|
||||
size_t pwlen = 0;
|
||||
|
||||
for (i=3; i < nread && hexdigitp (pw+i); i+=2)
|
||||
pw[pwlen++] = xtoi_2 (pw+i);
|
||||
pw[pwlen] = 0; /* make a C String */
|
||||
result = pw;
|
||||
pw = NULL;
|
||||
}
|
||||
else if (nread > 7 && !memcmp (pw, "ERR 111", 7)
|
||||
&& (pw[7] == ' ' || pw[7] == '\n') )
|
||||
{
|
||||
#ifdef SPWQ_USE_LOGGING
|
||||
log_info (_("canceled by user\n") );
|
||||
#endif
|
||||
*errorcode = 0; /* canceled */
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef SPWQ_USE_LOGGING
|
||||
log_error (_("problem with the agent\n"));
|
||||
#endif
|
||||
rc = SPWQ_ERR_RESPONSE;
|
||||
}
|
||||
|
||||
leave:
|
||||
if (errorcode)
|
||||
*errorcode = rc;
|
||||
if (fd != -1)
|
||||
close (fd);
|
||||
if (pw)
|
||||
spwq_free (pw);
|
||||
return result;
|
||||
}
|
@ -1,304 +0,0 @@
|
||||
/* trustlist.c - Maintain the list of trusted keys
|
||||
* Copyright (C) 2002 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 <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "agent.h"
|
||||
#include "../assuan/assuan.h" /* fixme: need a way to avoid assuan
|
||||
calls here */
|
||||
|
||||
static const char headerblurb[] =
|
||||
"# This is the list of trusted keys. Comments like this one and empty\n"
|
||||
"# lines are allowed but keep in mind that the entire file is integrity\n"
|
||||
"# protected by the use of a MAC, so changing the file does not make\n"
|
||||
"# much sense without the knowledge of the MAC key. Lines do have a\n"
|
||||
"# length limit but this is not serious limitation as the format of the\n"
|
||||
"# entries is fixed and checked by gpg-agent: A non-comment line starts\n"
|
||||
"# with optional white spaces, followed by exactly 40 hex character,\n"
|
||||
"# optioanlly followed by a flag character which my either be 'P', 'S'\n"
|
||||
"# or '*'. Additional data delimited with by a white space is ignored.\n"
|
||||
"\n";
|
||||
|
||||
|
||||
static FILE *trustfp;
|
||||
|
||||
|
||||
static int
|
||||
open_list (int append)
|
||||
{
|
||||
char *fname;
|
||||
|
||||
fname = make_filename (opt.homedir, "trustlist.txt", NULL);
|
||||
trustfp = fopen (fname, append? "a+":"r");
|
||||
if (!trustfp && errno == ENOENT)
|
||||
{
|
||||
trustfp = fopen (fname, "wx");
|
||||
if (!trustfp)
|
||||
{
|
||||
log_error ("can't create `%s': %s\n", fname, strerror (errno));
|
||||
xfree (fname);
|
||||
return seterr (File_Create_Error);
|
||||
}
|
||||
fputs (headerblurb, trustfp);
|
||||
fclose (trustfp);
|
||||
trustfp = fopen (fname, append? "a+":"r");
|
||||
}
|
||||
|
||||
if (!trustfp)
|
||||
{
|
||||
log_error ("can't open `%s': %s\n", fname, strerror (errno));
|
||||
xfree (fname);
|
||||
return seterr (File_Open_Error);
|
||||
}
|
||||
|
||||
/*FIXME: check the MAC */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Read the trustlist and return entry by entry. KEY must point to a
|
||||
buffer of at least 41 characters. KEYFLAG does return either 'P',
|
||||
'S' or '*'.
|
||||
|
||||
Reading a valid entry return 0, EOF returns -1 any other error
|
||||
returns the appropriate error code. */
|
||||
static int
|
||||
read_list (char *key, int *keyflag)
|
||||
{
|
||||
int rc;
|
||||
int c, i;
|
||||
char *p, line[256];
|
||||
|
||||
if (!trustfp)
|
||||
{
|
||||
rc = open_list (0);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (!fgets (line, DIM(line)-1, trustfp) )
|
||||
{
|
||||
if (feof (trustfp))
|
||||
return -1;
|
||||
return GNUPG_Read_Error;
|
||||
}
|
||||
|
||||
if (!*line || line[strlen(line)-1] != '\n')
|
||||
{
|
||||
/* eat until end of line */
|
||||
while ( (c=getc (trustfp)) != EOF && c != '\n')
|
||||
;
|
||||
return *line? GNUPG_Line_Too_Long: GNUPG_Incomplete_Line;
|
||||
}
|
||||
|
||||
/* Allow for emty lines and spaces */
|
||||
for (p=line; spacep (p); p++)
|
||||
;
|
||||
}
|
||||
while (!*p || *p == '\n' || *p == '#');
|
||||
|
||||
for (i=0; hexdigitp (p+i) && i < 40; i++)
|
||||
key[i] = p[i] >= 'a'? (p[i] & 0xdf): p[i];
|
||||
key[i] = 0;
|
||||
if (i!=40 || !(spacep (p+i) || p[i] == '\n'))
|
||||
{
|
||||
log_error ("invalid formatted fingerprint in trustlist\n");
|
||||
return GNUPG_Bad_Data;
|
||||
}
|
||||
assert (p[i]);
|
||||
if (p[i] == '\n')
|
||||
*keyflag = '*';
|
||||
else
|
||||
{
|
||||
i++;
|
||||
if ( p[i] == 'P' || p[i] == 'p')
|
||||
*keyflag = 'P';
|
||||
else if ( p[i] == 'S' || p[i] == 's')
|
||||
*keyflag = 'S';
|
||||
else if ( p[i] == '*')
|
||||
*keyflag = '*';
|
||||
else
|
||||
{
|
||||
log_error ("invalid keyflag in trustlist\n");
|
||||
return GNUPG_Bad_Data;
|
||||
}
|
||||
i++;
|
||||
if ( !(spacep (p+i) || p[i] == '\n'))
|
||||
{
|
||||
log_error ("invalid keyflag in trustlist\n");
|
||||
return GNUPG_Bad_Data;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check whether the given fpr is in our trustdb. We expect FPR to be
|
||||
an all uppercase hexstring of 40 characters. */
|
||||
int
|
||||
agent_istrusted (const char *fpr)
|
||||
{
|
||||
int rc;
|
||||
static char key[41];
|
||||
int keyflag;
|
||||
|
||||
if (trustfp)
|
||||
rewind (trustfp);
|
||||
while (!(rc=read_list (key, &keyflag)))
|
||||
{
|
||||
if (!strcmp (key, fpr))
|
||||
return 0;
|
||||
}
|
||||
if (rc != -1)
|
||||
{
|
||||
/* error in the trustdb - close it to give the user a chance for
|
||||
correction */
|
||||
fclose (trustfp);
|
||||
trustfp = NULL;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* write all trust entries to FP */
|
||||
int
|
||||
agent_listtrusted (void *assuan_context)
|
||||
{
|
||||
int rc;
|
||||
static char key[51];
|
||||
int keyflag;
|
||||
|
||||
if (trustfp)
|
||||
rewind (trustfp);
|
||||
while (!(rc=read_list (key, &keyflag)))
|
||||
{
|
||||
key[40] = ' ';
|
||||
key[41] = keyflag;
|
||||
key[42] = '\n';
|
||||
assuan_send_data (assuan_context, key, 43);
|
||||
assuan_send_data (assuan_context, NULL, 0); /* flush */
|
||||
}
|
||||
if (rc == -1)
|
||||
rc = 0;
|
||||
if (rc)
|
||||
{
|
||||
/* error in the trustdb - close it to give the user a chance for
|
||||
correction */
|
||||
fclose (trustfp);
|
||||
trustfp = NULL;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* Insert the given fpr into our trustdb. We expect FPR to be an all
|
||||
uppercase hexstring of 40 characters. FLAG is either 'P' or 'C'.
|
||||
This function does first check whether that key has alreay ben put
|
||||
into the trustdb and returns success in this case. Before a FPR
|
||||
actually gets inserted, the user is asked by means of the pin-entry
|
||||
whether this is actual wants he want to do.
|
||||
*/
|
||||
int
|
||||
agent_marktrusted (const char *name, const char *fpr, int flag)
|
||||
{
|
||||
int rc;
|
||||
static char key[41];
|
||||
int keyflag;
|
||||
char *desc;
|
||||
|
||||
if (trustfp)
|
||||
rewind (trustfp);
|
||||
while (!(rc=read_list (key, &keyflag)))
|
||||
{
|
||||
if (!strcmp (key, fpr))
|
||||
return 0;
|
||||
}
|
||||
fclose (trustfp);
|
||||
trustfp = NULL;
|
||||
if (rc != -1)
|
||||
return rc; /* error in the trustdb */
|
||||
|
||||
/* insert a new one */
|
||||
if (asprintf (&desc,
|
||||
"Please verify that the certificate identified as:%%0A"
|
||||
" \"%s\"%%0A"
|
||||
"has the fingerprint:%%0A"
|
||||
" %s", name, fpr) < 0 )
|
||||
return GNUPG_Out_Of_Core;
|
||||
rc = agent_get_confirmation (desc, "Correct", "No");
|
||||
free (desc);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (asprintf (&desc,
|
||||
"Do you ultimately trust%%0A"
|
||||
" \"%s\"%%0A"
|
||||
"to correctly certify user certificates?",
|
||||
name) < 0 )
|
||||
return GNUPG_Out_Of_Core;
|
||||
rc = agent_get_confirmation (desc, "Yes", "No");
|
||||
free (desc);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* now check again to avoid duplicates. Also open in append mode now */
|
||||
rc = open_list (1);
|
||||
if (rc)
|
||||
return rc;
|
||||
rewind (trustfp);
|
||||
while (!(rc=read_list (key, &keyflag)))
|
||||
{
|
||||
if (!strcmp (key, fpr))
|
||||
return 0;
|
||||
}
|
||||
if (rc != -1)
|
||||
{
|
||||
fclose (trustfp);
|
||||
trustfp = NULL;
|
||||
return rc; /* error in the trustdb */
|
||||
}
|
||||
rc = 0;
|
||||
|
||||
/* append the key */
|
||||
fflush (trustfp);
|
||||
fputs ("\n# ", trustfp);
|
||||
print_sanitized_string (trustfp, name, 0);
|
||||
fprintf (trustfp, "\n%s %c\n", fpr, flag);
|
||||
if (ferror (trustfp))
|
||||
rc = GNUPG_Write_Error;
|
||||
|
||||
/* close because we are in append mode */
|
||||
if (fclose (trustfp))
|
||||
rc = GNUPG_File_Error;
|
||||
trustfp = NULL;
|
||||
return rc;
|
||||
}
|
250
assuan/ChangeLog
250
assuan/ChangeLog
@ -1,250 +0,0 @@
|
||||
2002-08-16 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan.h: Renamed Bad_Certificate_Path to Bad_Certificate_Chain.
|
||||
|
||||
2002-07-30 Werner Koch <wk@gnupg.org>
|
||||
|
||||
Changed the license from GPL to LGPL.
|
||||
|
||||
2002-07-23 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-handler.c (_IO_cookie_io_functions_t): Define it here if
|
||||
it does not exists.
|
||||
|
||||
2002-06-27 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-pipe-connect.c (assuan_pipe_connect): No special handling
|
||||
for the log_fd and stderr. Connect stderr to /dev/null if it
|
||||
should not be retained.
|
||||
|
||||
2002-06-26 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-buffer.c (assuan_write_line): Make sure we never
|
||||
accidently print an extra LF.
|
||||
|
||||
2002-05-23 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-util.c (assuan_set_io_func): New.
|
||||
* assuan-buffer.c (writen, readline): Use the new functions
|
||||
instead of pth.
|
||||
* assuan-socket-server.c (accept_connection): Don't use the
|
||||
pth_accept - using the assuan included accept code would be a bad
|
||||
idea within Pth so we don't need a replacement function.
|
||||
|
||||
2002-05-22 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-socket-server.c (assuan_init_connected_socket_server): New.
|
||||
(accept_connection): Factored most code out to..
|
||||
(accept_connection_bottom): .. new function.
|
||||
|
||||
2002-04-04 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-buffer.c (my_log_prefix): New. Use it for all i/o debug
|
||||
output.
|
||||
|
||||
2002-03-06 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-client.c (_assuan_read_from_server): Detect END.
|
||||
(assuan_transact): Pass it to the data callback.
|
||||
|
||||
2002-02-27 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-client.c (assuan_transact): Add 2 more arguments to
|
||||
support status lines. Passing NULL yields the old behaviour.
|
||||
|
||||
* assuan-handler.c (process_request): Flush data lines send
|
||||
without using the data fp.
|
||||
|
||||
2002-02-14 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-inquire.c (assuan_inquire): Check for a cancel command
|
||||
and return ASSUAN_Canceled. Allow for non-data inquiry.
|
||||
|
||||
* assuan.h: Add a few token specific error codes.
|
||||
|
||||
2002-02-13 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-defs.h (assuan_context_s): New var CLIENT_PID.
|
||||
* assuan-pipe-server.c (_assuan_new_context): set default value.
|
||||
* assuan-socket-server.c (accept_connection): get the actual pid.
|
||||
|
||||
2002-02-12 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-buffer.c (writen,readline) [USE_GNU_PT]: Use pth_read/write.
|
||||
* assuan-socket-server.c (accept_connection) [USE_GNU_PTH]: Ditto.
|
||||
|
||||
2002-02-01 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* Makefile.am (MOSTLYCLEANFILES): New variable.
|
||||
|
||||
2002-01-23 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-socket-connect.c (LOGERRORX): and removed typo.
|
||||
|
||||
2002-01-22 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* assuan-socket-connect.c (LOGERRORX): Reverse arguments to fputs.
|
||||
|
||||
2002-01-21 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-connect.c: Move all except assuan_get_pid to...
|
||||
* assuan-pipe-connect.c: this.
|
||||
(assuan_pipe_disconnect): Removed.
|
||||
(do_finish, do_deinit): New
|
||||
(assuan_pipe_connect): and set them into the context.
|
||||
* assuan-socket-connect.c: New.
|
||||
|
||||
* assuan-util.c (_assuan_log_sanitized_string): New.
|
||||
|
||||
* assuan-pipe-server.c (assuan_init_pipe_server): Factored most
|
||||
code out to ...
|
||||
(_assuan_new_context): new func.
|
||||
(_assuan_release_context): New
|
||||
* assuan-connect.c (assuan_pipe_connect): Use the new functions.
|
||||
|
||||
2002-01-20 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan.h: Added Invalid Option error code.
|
||||
|
||||
* assuan-handler.c (std_handler_option): New.
|
||||
(std_cmd_tbl): Add OPTION as standard command.
|
||||
(assuan_register_option_handler): New.
|
||||
(dispatch_command): Use case insensitive matching as a fallback.
|
||||
(my_strcasecmp): New.
|
||||
|
||||
2002-01-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-buffer.c (_assuan_read_line): Add output logging.
|
||||
(assuan_write_line): Ditto.
|
||||
(_assuan_cookie_write_data): Ditto.
|
||||
(_assuan_cookie_write_flush): Ditto.
|
||||
* assuan-util.c (_assuan_log_print_buffer): New.
|
||||
(assuan_set_log_stream): New.
|
||||
(assuan_begin_confidential): New.
|
||||
(assuan_end_confidential): New.
|
||||
|
||||
* assuan-defs.h: Add a few handler variables.
|
||||
* assuan-pipe-server.c (assuan_deinit_pipe_server): Removed.
|
||||
(deinit_pipe_server): New.
|
||||
(assuan_deinit_server): New. Changed all callers to use this.
|
||||
* assuan-listen.c (assuan_accept): Use the accept handler.
|
||||
* assuan-handler.c (process_request): Use the close Handler.
|
||||
* assuan-socket-server.c: New.
|
||||
|
||||
2002-01-14 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-client.c (_assuan_read_from_server): Skip spaces after
|
||||
the keyword.
|
||||
|
||||
2002-01-03 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-handler.c (assuan_set_okay_line): New.
|
||||
(process_request): And use it here.
|
||||
|
||||
2002-01-02 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-inquire.c (init_membuf,put_membuf,get_membuf): Apply a
|
||||
hidden 0 behind the buffer so that the buffer can be used as a
|
||||
string in certain contexts.
|
||||
|
||||
2001-12-14 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* assuan-connect.c (assuan_pipe_connect): New argument
|
||||
FD_CHILD_LIST. Don't close those fds.
|
||||
* assuan.h: Likewise for prototype.
|
||||
|
||||
2001-12-14 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-listen.c (assuan_close_input_fd): New.
|
||||
(assuan_close_output_fd): New.
|
||||
* assuan-handler.c (std_handler_reset): Always close them after a
|
||||
reset command.
|
||||
(std_handler_bye): Likewise.
|
||||
|
||||
2001-12-14 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* assuan-buffer.c (_assuan_read_line): New variable ATTICLEN, use
|
||||
it to save the length of the attic line.
|
||||
Rediddle the code a bit to make it more clear what happens.
|
||||
|
||||
2001-12-14 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* assuan-defs.h (LINELENGTH): Define as ASSUAN_LINELENGTH.
|
||||
assuan.h: Define ASSUAN_LINELENGTH.
|
||||
|
||||
2001-12-13 Marcus Brinkmann <marcus@g10code.de>
|
||||
|
||||
* assuan-buffer.c (assuan_read_line): Fix order of execution to
|
||||
get correct return values.
|
||||
|
||||
2001-12-13 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-handler.c (assuan_get_active_fds): Fixed silly bug,
|
||||
pretty obvious that nobody ever tested this function.
|
||||
|
||||
2001-12-12 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-connect.c (assuan_pipe_connect): Implemented the inital
|
||||
handshake.
|
||||
* assuan-client.c (read_from_server): Renamed to
|
||||
(_assuan_read_from_server): this and made external.
|
||||
|
||||
* assuan-listen.c (assuan_set_hello_line): New.
|
||||
(assuan_accept): Use a custom hello line is available.
|
||||
|
||||
* assuan-buffer.c (assuan_read_line): New.
|
||||
(assuan_pending_line): New.
|
||||
(_assuan_write_line): Renamed to ..
|
||||
(assuan_write_line): this, made public and changed all callers.
|
||||
|
||||
2001-12-04 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-connect.c (assuan_pipe_connect): Add more error reporting.
|
||||
* assuan-client.c: New.
|
||||
|
||||
* assuan-inquire.c: New.
|
||||
* assuan-handler.c (process_request): Check for nested invocations.
|
||||
|
||||
2001-11-27 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-handler.c (assuan_register_input_notify): New.
|
||||
(assuan_register_output_notify): New.
|
||||
|
||||
2001-11-26 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan.h: Added more status codes.
|
||||
|
||||
2001-11-25 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-handler.c (assuan_register_bye_notify)
|
||||
(assuan_register_reset_notify)
|
||||
(assuan_register_cancel_notify): New and call them from the
|
||||
standard handlers.
|
||||
(assuan_process): Moved bulk of function to ..
|
||||
(process_request): .. new.
|
||||
(assuan_process_next): One shot version of above.
|
||||
(assuan_get_active_fds): New.
|
||||
|
||||
2001-11-24 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* assuan-connect.c (assuan_get_pid): New.
|
||||
|
||||
* assuan-buffer.c (_assuan_read_line): Deal with reads of more
|
||||
than a line.
|
||||
* assuan-defs.h: Add space in the context for this.
|
||||
|
||||
|
||||
***********************************************************
|
||||
* Please note that Assuan is maintained as part of GnuPG. *
|
||||
* You may find it source-copied in other packages. *
|
||||
***********************************************************
|
||||
|
||||
Copyright 2001, 2002 Free Software Foundation, Inc.
|
||||
|
||||
This file is free software; as a special exception the author gives
|
||||
unlimited permission to copy and/or distribute it, with or without
|
||||
modifications, as long as this notice is preserved.
|
||||
|
||||
This file is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
@ -1,49 +0,0 @@
|
||||
# Assuan Makefile
|
||||
# Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of Assuan.
|
||||
#
|
||||
# Assuan is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as
|
||||
# published by the Free Software Foundation; either version 2.1 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# Assuan 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
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
EXTRA_DIST = mkerrors
|
||||
INCLUDES = -I.. -I$(top_srcdir)/include
|
||||
BUILT_SOURCES = assuan-errors.c
|
||||
MOSTLYCLEANFILES = assuan-errors.c
|
||||
|
||||
noinst_LIBRARIES = libassuan.a
|
||||
|
||||
|
||||
#libassuan_a_LDFLAGS =
|
||||
libassuan_a_SOURCES = \
|
||||
assuan.h \
|
||||
assuan-defs.h \
|
||||
assuan-util.c \
|
||||
assuan-errors.c \
|
||||
assuan-buffer.c \
|
||||
assuan-handler.c \
|
||||
assuan-inquire.c \
|
||||
assuan-listen.c \
|
||||
assuan-connect.c \
|
||||
assuan-client.c \
|
||||
assuan-pipe-server.c \
|
||||
assuan-socket-server.c \
|
||||
assuan-pipe-connect.c \
|
||||
assuan-socket-connect.c
|
||||
|
||||
|
||||
assuan-errors.c : assuan.h
|
||||
$(srcdir)/mkerrors < $(srcdir)/assuan.h > assuan-errors.c
|
@ -1,443 +0,0 @@
|
||||
/* assuan-buffer.c - read and send data
|
||||
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of Assuan.
|
||||
*
|
||||
* Assuan is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Assuan 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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 <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include "assuan-defs.h"
|
||||
|
||||
#ifdef HAVE_JNLIB_LOGGING
|
||||
#include "../jnlib/logging.h"
|
||||
#endif
|
||||
|
||||
|
||||
static const char *
|
||||
my_log_prefix (void)
|
||||
{
|
||||
#ifdef HAVE_JNLIB_LOGGING
|
||||
return log_get_prefix (NULL);
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
writen ( int fd, const char *buffer, size_t length )
|
||||
{
|
||||
while (length)
|
||||
{
|
||||
int nwritten = _assuan_write_wrapper?
|
||||
_assuan_write_wrapper (fd, buffer, length):
|
||||
write (fd, buffer, length);
|
||||
|
||||
if (nwritten < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return -1; /* write error */
|
||||
}
|
||||
length -= nwritten;
|
||||
buffer += nwritten;
|
||||
}
|
||||
return 0; /* okay */
|
||||
}
|
||||
|
||||
/* read an entire line */
|
||||
static int
|
||||
readline (int fd, char *buf, size_t buflen, int *r_nread, int *eof)
|
||||
{
|
||||
size_t nleft = buflen;
|
||||
char *p;
|
||||
|
||||
*eof = 0;
|
||||
*r_nread = 0;
|
||||
while (nleft > 0)
|
||||
{
|
||||
int n = _assuan_read_wrapper?
|
||||
_assuan_read_wrapper (fd, buf, nleft):
|
||||
read (fd, buf, nleft);
|
||||
|
||||
if (n < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return -1; /* read error */
|
||||
}
|
||||
else if (!n)
|
||||
{
|
||||
*eof = 1;
|
||||
break; /* allow incomplete lines */
|
||||
}
|
||||
p = buf;
|
||||
nleft -= n;
|
||||
buf += n;
|
||||
*r_nread += n;
|
||||
|
||||
for (; n && *p != '\n'; n--, p++)
|
||||
;
|
||||
if (n)
|
||||
break; /* at least one full line available - that's enough for now */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_assuan_read_line (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
char *line = ctx->inbound.line;
|
||||
int n, nread, atticlen;
|
||||
int rc;
|
||||
|
||||
if (ctx->inbound.eof)
|
||||
return -1;
|
||||
|
||||
atticlen = ctx->inbound.attic.linelen;
|
||||
if (atticlen)
|
||||
{
|
||||
memcpy (line, ctx->inbound.attic.line, atticlen);
|
||||
ctx->inbound.attic.linelen = 0;
|
||||
for (n=0; n < atticlen && line[n] != '\n'; n++)
|
||||
;
|
||||
if (n < atticlen)
|
||||
{
|
||||
rc = 0; /* found another line in the attic */
|
||||
nread = atticlen;
|
||||
atticlen = 0;
|
||||
}
|
||||
else
|
||||
{ /* read the rest */
|
||||
assert (atticlen < LINELENGTH);
|
||||
rc = readline (ctx->inbound.fd, line + atticlen,
|
||||
LINELENGTH - atticlen, &nread, &ctx->inbound.eof);
|
||||
}
|
||||
}
|
||||
else
|
||||
rc = readline (ctx->inbound.fd, line, LINELENGTH,
|
||||
&nread, &ctx->inbound.eof);
|
||||
if (rc)
|
||||
{
|
||||
if (ctx->log_fp)
|
||||
fprintf (ctx->log_fp, "%s[%p] <- [Error: %s]\n",
|
||||
my_log_prefix (), ctx, strerror (errno));
|
||||
return ASSUAN_Read_Error;
|
||||
}
|
||||
if (!nread)
|
||||
{
|
||||
assert (ctx->inbound.eof);
|
||||
if (ctx->log_fp)
|
||||
fprintf (ctx->log_fp, "%s[%p] <- [EOF]\n", my_log_prefix (),ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->inbound.attic.pending = 0;
|
||||
nread += atticlen;
|
||||
for (n=0; n < nread; n++)
|
||||
{
|
||||
if (line[n] == '\n')
|
||||
{
|
||||
if (n+1 < nread)
|
||||
{
|
||||
char *s, *d;
|
||||
int i;
|
||||
|
||||
n++;
|
||||
/* we have to copy the rest because the handlers are
|
||||
allowed to modify the passed buffer */
|
||||
for (d=ctx->inbound.attic.line, s=line+n, i=nread-n; i; i--)
|
||||
{
|
||||
if (*s=='\n')
|
||||
ctx->inbound.attic.pending = 1;
|
||||
*d++ = *s++;
|
||||
}
|
||||
ctx->inbound.attic.linelen = nread-n;
|
||||
n--;
|
||||
}
|
||||
if (n && line[n-1] == '\r')
|
||||
n--;
|
||||
line[n] = 0;
|
||||
ctx->inbound.linelen = n;
|
||||
if (ctx->log_fp)
|
||||
{
|
||||
fprintf (ctx->log_fp, "%s[%p] <- ", my_log_prefix (), ctx);
|
||||
if (ctx->confidential)
|
||||
fputs ("[Confidential data not shown]", ctx->log_fp);
|
||||
else
|
||||
_assuan_log_print_buffer (ctx->log_fp,
|
||||
ctx->inbound.line,
|
||||
ctx->inbound.linelen);
|
||||
putc ('\n', ctx->log_fp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->log_fp)
|
||||
fprintf (ctx->log_fp, "%s[%p] <- [Invalid line]\n", my_log_prefix (), ctx);
|
||||
*line = 0;
|
||||
ctx->inbound.linelen = 0;
|
||||
return ctx->inbound.eof? ASSUAN_Line_Not_Terminated : ASSUAN_Line_Too_Long;
|
||||
}
|
||||
|
||||
|
||||
/* Read the next line from the client or server and return a pointer
|
||||
to a buffer with holding that line. linelen returns the length of
|
||||
the line. This buffer is valid until another read operation is
|
||||
done on this buffer. The caller is allowed to modify this buffer.
|
||||
He should only use the buffer if the function returns without an
|
||||
error.
|
||||
|
||||
Returns: 0 on success or an assuan error code
|
||||
See also: assuan_pending_line().
|
||||
*/
|
||||
AssuanError
|
||||
assuan_read_line (ASSUAN_CONTEXT ctx, char **line, size_t *linelen)
|
||||
{
|
||||
AssuanError err;
|
||||
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
|
||||
err = _assuan_read_line (ctx);
|
||||
*line = ctx->inbound.line;
|
||||
*linelen = ctx->inbound.linelen;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Return true when a full line is pending for a read, without the need
|
||||
for actual IO */
|
||||
int
|
||||
assuan_pending_line (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
return ctx && ctx->inbound.attic.pending;
|
||||
}
|
||||
|
||||
|
||||
AssuanError
|
||||
assuan_write_line (ASSUAN_CONTEXT ctx, const char *line )
|
||||
{
|
||||
int rc;
|
||||
size_t len;
|
||||
const char *s;
|
||||
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
|
||||
/* Make sure that we never take a LF from the user - this might
|
||||
violate the protocol. */
|
||||
s = strchr (line, '\n');
|
||||
len = s? (s-line) : strlen (line);
|
||||
|
||||
/* fixme: we should do some kind of line buffering. */
|
||||
if (ctx->log_fp)
|
||||
{
|
||||
fprintf (ctx->log_fp, "%s[%p] -> ", my_log_prefix (), ctx);
|
||||
if (s)
|
||||
fputs ("[supplied line contained a LF]", ctx->log_fp);
|
||||
if (ctx->confidential)
|
||||
fputs ("[Confidential data not shown]", ctx->log_fp);
|
||||
else
|
||||
_assuan_log_print_buffer (ctx->log_fp, line, len);
|
||||
putc ('\n', ctx->log_fp);
|
||||
}
|
||||
|
||||
rc = writen (ctx->outbound.fd, line, len);
|
||||
if (rc)
|
||||
rc = ASSUAN_Write_Error;
|
||||
if (!rc)
|
||||
{
|
||||
rc = writen (ctx->outbound.fd, "\n", 1);
|
||||
if (rc)
|
||||
rc = ASSUAN_Write_Error;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Write out the data in buffer as datalines with line wrapping and
|
||||
percent escaping. This fucntion is used for GNU's custom streams */
|
||||
int
|
||||
_assuan_cookie_write_data (void *cookie, const char *buffer, size_t size)
|
||||
{
|
||||
ASSUAN_CONTEXT ctx = cookie;
|
||||
char *line;
|
||||
size_t linelen;
|
||||
|
||||
if (ctx->outbound.data.error)
|
||||
return 0;
|
||||
|
||||
line = ctx->outbound.data.line;
|
||||
linelen = ctx->outbound.data.linelen;
|
||||
line += linelen;
|
||||
while (size)
|
||||
{
|
||||
/* insert data line header */
|
||||
if (!linelen)
|
||||
{
|
||||
*line++ = 'D';
|
||||
*line++ = ' ';
|
||||
linelen += 2;
|
||||
}
|
||||
|
||||
/* copy data, keep some space for the CRLF and to escape one character */
|
||||
while (size && linelen < LINELENGTH-2-2)
|
||||
{
|
||||
if (*buffer == '%' || *buffer == '\r' || *buffer == '\n')
|
||||
{
|
||||
sprintf (line, "%%%02X", *(unsigned char*)buffer);
|
||||
line += 3;
|
||||
linelen += 3;
|
||||
buffer++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*line++ = *buffer++;
|
||||
linelen++;
|
||||
}
|
||||
size--;
|
||||
}
|
||||
|
||||
if (linelen >= LINELENGTH-2-2)
|
||||
{
|
||||
if (ctx->log_fp)
|
||||
{
|
||||
fprintf (ctx->log_fp, "%s[%p] -> ", my_log_prefix (), ctx);
|
||||
if (ctx->confidential)
|
||||
fputs ("[Confidential data not shown]", ctx->log_fp);
|
||||
else
|
||||
_assuan_log_print_buffer (ctx->log_fp,
|
||||
ctx->outbound.data.line,
|
||||
linelen);
|
||||
putc ('\n', ctx->log_fp);
|
||||
}
|
||||
*line++ = '\n';
|
||||
linelen++;
|
||||
if (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen))
|
||||
{
|
||||
ctx->outbound.data.error = ASSUAN_Write_Error;
|
||||
return 0;
|
||||
}
|
||||
line = ctx->outbound.data.line;
|
||||
linelen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->outbound.data.linelen = linelen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Write out any buffered data
|
||||
This fucntion is used for GNU's custom streams */
|
||||
int
|
||||
_assuan_cookie_write_flush (void *cookie)
|
||||
{
|
||||
ASSUAN_CONTEXT ctx = cookie;
|
||||
char *line;
|
||||
size_t linelen;
|
||||
|
||||
if (ctx->outbound.data.error)
|
||||
return 0;
|
||||
|
||||
line = ctx->outbound.data.line;
|
||||
linelen = ctx->outbound.data.linelen;
|
||||
line += linelen;
|
||||
if (linelen)
|
||||
{
|
||||
if (ctx->log_fp)
|
||||
{
|
||||
fprintf (ctx->log_fp, "%s[%p] -> ", my_log_prefix (), ctx);
|
||||
if (ctx->confidential)
|
||||
fputs ("[Confidential data not shown]", ctx->log_fp);
|
||||
else
|
||||
_assuan_log_print_buffer (ctx->log_fp,
|
||||
ctx->outbound.data.line,
|
||||
linelen);
|
||||
putc ('\n', ctx->log_fp);
|
||||
}
|
||||
*line++ = '\n';
|
||||
linelen++;
|
||||
if (writen (ctx->outbound.fd, ctx->outbound.data.line, linelen))
|
||||
{
|
||||
ctx->outbound.data.error = ASSUAN_Write_Error;
|
||||
return 0;
|
||||
}
|
||||
ctx->outbound.data.linelen = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* assuan_send_data:
|
||||
* @ctx: An assuan context
|
||||
* @buffer: Data to send or NULL to flush
|
||||
* @length: length of the data to send/
|
||||
*
|
||||
* This function may be used by the server or the client to send data
|
||||
* lines. The data will be escaped as required by the Assuan protocol
|
||||
* and may get buffered until a line is full. To force sending the
|
||||
* data out @buffer may be passed as NULL (in which case @length must
|
||||
* also be 0); however when used by a client this flush operation does
|
||||
* also send the terminating "END" command to terminate the reponse on
|
||||
* a INQUIRE response. However, when assuan_transact() is used, this
|
||||
* function takes care of sending END itself.
|
||||
*
|
||||
* Return value: 0 on success or an error code
|
||||
**/
|
||||
|
||||
AssuanError
|
||||
assuan_send_data (ASSUAN_CONTEXT ctx, const void *buffer, size_t length)
|
||||
{
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
if (!buffer && length)
|
||||
return ASSUAN_Invalid_Value;
|
||||
|
||||
if (!buffer)
|
||||
{ /* flush what we have */
|
||||
_assuan_cookie_write_flush (ctx);
|
||||
if (ctx->outbound.data.error)
|
||||
return ctx->outbound.data.error;
|
||||
if (!ctx->is_server)
|
||||
return assuan_write_line (ctx, "END");
|
||||
}
|
||||
else
|
||||
{
|
||||
_assuan_cookie_write_data (ctx, buffer, length);
|
||||
if (ctx->outbound.data.error)
|
||||
return ctx->outbound.data.error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,225 +0,0 @@
|
||||
/* assuan-client.c - client functions
|
||||
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of Assuan.
|
||||
*
|
||||
* Assuan is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Assuan 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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 <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "assuan-defs.h"
|
||||
|
||||
#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
|
||||
*(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
|
||||
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
|
||||
|
||||
|
||||
AssuanError
|
||||
_assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off)
|
||||
{
|
||||
char *line;
|
||||
int linelen;
|
||||
AssuanError rc;
|
||||
|
||||
*okay = 0;
|
||||
*off = 0;
|
||||
do
|
||||
{
|
||||
rc = _assuan_read_line (ctx);
|
||||
if (rc)
|
||||
return rc;
|
||||
line = ctx->inbound.line;
|
||||
linelen = ctx->inbound.linelen;
|
||||
}
|
||||
while (*line == '#' || !linelen);
|
||||
|
||||
if (linelen >= 1
|
||||
&& line[0] == 'D' && line[1] == ' ')
|
||||
{
|
||||
*okay = 2; /* data line */
|
||||
*off = 2;
|
||||
}
|
||||
else if (linelen >= 1
|
||||
&& line[0] == 'S'
|
||||
&& (line[1] == '\0' || line[1] == ' '))
|
||||
{
|
||||
*okay = 4;
|
||||
*off = 1;
|
||||
while (line[*off] == ' ')
|
||||
++*off;
|
||||
}
|
||||
else if (linelen >= 2
|
||||
&& line[0] == 'O' && line[1] == 'K'
|
||||
&& (line[2] == '\0' || line[2] == ' '))
|
||||
{
|
||||
*okay = 1;
|
||||
*off = 2;
|
||||
while (line[*off] == ' ')
|
||||
++*off;
|
||||
}
|
||||
else if (linelen >= 3
|
||||
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
|
||||
&& (line[3] == '\0' || line[3] == ' '))
|
||||
{
|
||||
*okay = 0;
|
||||
*off = 3;
|
||||
while (line[*off] == ' ')
|
||||
++*off;
|
||||
}
|
||||
else if (linelen >= 7
|
||||
&& line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
|
||||
&& line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
|
||||
&& line[6] == 'E'
|
||||
&& (line[7] == '\0' || line[7] == ' '))
|
||||
{
|
||||
*okay = 3;
|
||||
*off = 7;
|
||||
while (line[*off] == ' ')
|
||||
++*off;
|
||||
}
|
||||
else if (linelen >= 3
|
||||
&& line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
|
||||
&& (line[3] == '\0' || line[3] == ' '))
|
||||
{
|
||||
*okay = 5; /* end line */
|
||||
*off = 3;
|
||||
}
|
||||
else
|
||||
rc = ASSUAN_Invalid_Response;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* assuan_transact:
|
||||
* @ctx: The Assuan context
|
||||
* @command: Coimmand line to be send to server
|
||||
* @data_cb: Callback function for data lines
|
||||
* @data_cb_arg: first argument passed to @data_cb
|
||||
* @inquire_cb: Callback function for a inquire response
|
||||
* @inquire_cb_arg: first argument passed to @inquire_cb
|
||||
* @status_cb: Callback function for a status response
|
||||
* @status_cb_arg: first argument passed to @status_cb
|
||||
*
|
||||
* FIXME: Write documentation
|
||||
*
|
||||
* Return value: 0 on success or error code. The error code may be
|
||||
* the one one returned by the server in error lines or from the
|
||||
* callback functions.
|
||||
**/
|
||||
AssuanError
|
||||
assuan_transact (ASSUAN_CONTEXT ctx,
|
||||
const char *command,
|
||||
AssuanError (*data_cb)(void *, const void *, size_t),
|
||||
void *data_cb_arg,
|
||||
AssuanError (*inquire_cb)(void*, const char *),
|
||||
void *inquire_cb_arg,
|
||||
AssuanError (*status_cb)(void*, const char *),
|
||||
void *status_cb_arg)
|
||||
{
|
||||
int rc, okay, off;
|
||||
unsigned char *line;
|
||||
int linelen;
|
||||
|
||||
rc = assuan_write_line (ctx, command);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
again:
|
||||
rc = _assuan_read_from_server (ctx, &okay, &off);
|
||||
if (rc)
|
||||
return rc; /* error reading from server */
|
||||
|
||||
line = ctx->inbound.line + off;
|
||||
linelen = ctx->inbound.linelen - off;
|
||||
|
||||
if (!okay)
|
||||
{
|
||||
rc = atoi (line);
|
||||
if (rc < 100)
|
||||
rc = ASSUAN_Server_Fault;
|
||||
}
|
||||
else if (okay == 2)
|
||||
{
|
||||
if (!data_cb)
|
||||
rc = ASSUAN_No_Data_Callback;
|
||||
else
|
||||
{
|
||||
unsigned char *s, *d;
|
||||
|
||||
for (s=d=line; linelen; linelen--)
|
||||
{
|
||||
if (*s == '%' && linelen > 2)
|
||||
{ /* handle escaping */
|
||||
s++;
|
||||
*d++ = xtoi_2 (s);
|
||||
s += 2;
|
||||
linelen -= 2;
|
||||
}
|
||||
else
|
||||
*d++ = *s++;
|
||||
}
|
||||
*d = 0; /* add a hidden string terminator */
|
||||
rc = data_cb (data_cb_arg, line, d - line);
|
||||
if (!rc)
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
else if (okay == 3)
|
||||
{
|
||||
if (!inquire_cb)
|
||||
{
|
||||
assuan_write_line (ctx, "END"); /* get out of inquire mode */
|
||||
_assuan_read_from_server (ctx, &okay, &off); /* dummy read */
|
||||
rc = ASSUAN_No_Inquire_Callback;
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = inquire_cb (inquire_cb_arg, line);
|
||||
if (!rc)
|
||||
rc = assuan_send_data (ctx, NULL, 0); /* flush and send END */
|
||||
if (!rc)
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
else if (okay == 4)
|
||||
{
|
||||
if (status_cb)
|
||||
rc = status_cb (status_cb_arg, line);
|
||||
if (!rc)
|
||||
goto again;
|
||||
}
|
||||
else if (okay == 5)
|
||||
{
|
||||
if (!data_cb)
|
||||
rc = ASSUAN_No_Data_Callback;
|
||||
else
|
||||
{
|
||||
rc = data_cb (data_cb_arg, NULL, 0);
|
||||
if (!rc)
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -1,54 +0,0 @@
|
||||
/* assuan-connect.c - Establish a connection (client)
|
||||
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of Assuan.
|
||||
*
|
||||
* Assuan is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Assuan 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "assuan-defs.h"
|
||||
|
||||
/* Disconnect and release the context CTX. */
|
||||
void
|
||||
assuan_disconnect (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
if (ctx)
|
||||
{
|
||||
assuan_write_line (ctx, "BYE");
|
||||
ctx->finish_handler (ctx);
|
||||
ctx->deinit_handler (ctx);
|
||||
ctx->deinit_handler = NULL;
|
||||
_assuan_release_context (ctx);
|
||||
}
|
||||
}
|
||||
|
||||
pid_t
|
||||
assuan_get_pid (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
return ctx ? ctx->pid : -1;
|
||||
}
|
@ -1,144 +0,0 @@
|
||||
/* assuan-defs.c - Internal definitions to Assuan
|
||||
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of Assuan.
|
||||
*
|
||||
* Assuan is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Assuan 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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 ASSUAN_DEFS_H
|
||||
#define ASSUAN_DEFS_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "assuan.h"
|
||||
|
||||
#define LINELENGTH ASSUAN_LINELENGTH
|
||||
|
||||
struct cmdtbl_s {
|
||||
const char *name;
|
||||
int cmd_id;
|
||||
int (*handler)(ASSUAN_CONTEXT, char *line);
|
||||
};
|
||||
|
||||
struct assuan_context_s {
|
||||
AssuanError err_no;
|
||||
const char *err_str;
|
||||
int os_errno; /* last system error number used with certain error codes*/
|
||||
|
||||
int confidential;
|
||||
int is_server; /* set if this is context belongs to a server */
|
||||
int in_inquire;
|
||||
char *hello_line;
|
||||
char *okay_line; /* see assan_set_okay_line() */
|
||||
|
||||
void *user_pointer; /* for assuan_[gs]et_pointer () */
|
||||
|
||||
FILE *log_fp;
|
||||
|
||||
struct {
|
||||
int fd;
|
||||
int eof;
|
||||
char line[LINELENGTH];
|
||||
int linelen; /* w/o CR, LF - might not be the same as
|
||||
strlen(line) due to embedded nuls. However a nul
|
||||
is always written at this pos */
|
||||
struct {
|
||||
char line[LINELENGTH];
|
||||
int linelen ;
|
||||
int pending; /* i.e. at least one line is available in the attic */
|
||||
} attic;
|
||||
} inbound;
|
||||
|
||||
struct {
|
||||
int fd;
|
||||
struct {
|
||||
FILE *fp;
|
||||
char line[LINELENGTH];
|
||||
int linelen;
|
||||
int error;
|
||||
} data;
|
||||
} outbound;
|
||||
|
||||
int pipe_mode; /* We are in pipe mode, i.e. we can handle just one
|
||||
connection and must terminate then */
|
||||
pid_t pid; /* In pipe mode, the pid of the child server process.
|
||||
In socket mode, the pid of the server */
|
||||
int listen_fd; /* The fd we are listening on (used by socket servers) */
|
||||
int connected_fd; /* helper */
|
||||
|
||||
pid_t client_pid; /* for a socket server the PID of the client or -1
|
||||
if not available */
|
||||
|
||||
void (*deinit_handler)(ASSUAN_CONTEXT);
|
||||
int (*accept_handler)(ASSUAN_CONTEXT);
|
||||
int (*finish_handler)(ASSUAN_CONTEXT);
|
||||
|
||||
struct cmdtbl_s *cmdtbl;
|
||||
size_t cmdtbl_used; /* used entries */
|
||||
size_t cmdtbl_size; /* allocated size of table */
|
||||
|
||||
void (*bye_notify_fnc)(ASSUAN_CONTEXT);
|
||||
void (*reset_notify_fnc)(ASSUAN_CONTEXT);
|
||||
void (*cancel_notify_fnc)(ASSUAN_CONTEXT);
|
||||
int (*option_handler_fnc)(ASSUAN_CONTEXT,const char*, const char*);
|
||||
void (*input_notify_fnc)(ASSUAN_CONTEXT, const char *);
|
||||
void (*output_notify_fnc)(ASSUAN_CONTEXT, const char *);
|
||||
|
||||
int input_fd; /* set by INPUT command */
|
||||
int output_fd; /* set by OUTPUT command */
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*-- assuan-pipe-server.c --*/
|
||||
int _assuan_new_context (ASSUAN_CONTEXT *r_ctx);
|
||||
void _assuan_release_context (ASSUAN_CONTEXT ctx);
|
||||
|
||||
|
||||
/*-- assuan-handler.c --*/
|
||||
int _assuan_register_std_commands (ASSUAN_CONTEXT ctx);
|
||||
|
||||
/*-- assuan-buffer.c --*/
|
||||
int _assuan_read_line (ASSUAN_CONTEXT ctx);
|
||||
int _assuan_cookie_write_data (void *cookie, const char *buffer, size_t size);
|
||||
int _assuan_cookie_write_flush (void *cookie);
|
||||
|
||||
/*-- assuan-client.c --*/
|
||||
AssuanError _assuan_read_from_server (ASSUAN_CONTEXT ctx, int *okay, int *off);
|
||||
|
||||
|
||||
/*-- assuan-util.c --*/
|
||||
extern ssize_t (*_assuan_read_wrapper)(int,void*,size_t);
|
||||
extern ssize_t (*_assuan_write_wrapper)(int,const void*,size_t);
|
||||
|
||||
void *_assuan_malloc (size_t n);
|
||||
void *_assuan_calloc (size_t n, size_t m);
|
||||
void *_assuan_realloc (void *p, size_t n);
|
||||
void _assuan_free (void *p);
|
||||
|
||||
#define xtrymalloc(a) _assuan_malloc ((a))
|
||||
#define xtrycalloc(a,b) _assuan_calloc ((a),(b))
|
||||
#define xtryrealloc(a,b) _assuan_realloc((a),(b))
|
||||
#define xfree(a) _assuan_free ((a))
|
||||
|
||||
#define set_error(c,e,t) assuan_set_error ((c), ASSUAN_ ## e, (t))
|
||||
|
||||
void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length);
|
||||
void _assuan_log_sanitized_string (const char *string);
|
||||
|
||||
|
||||
#endif /*ASSUAN_DEFS_H*/
|
||||
|
@ -1,708 +0,0 @@
|
||||
/* assuan-handler.c - dispatch commands
|
||||
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of Assuan.
|
||||
*
|
||||
* Assuan is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Assuan 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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 <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "assuan-defs.h"
|
||||
|
||||
#define spacep(p) (*(p) == ' ' || *(p) == '\t')
|
||||
#define digitp(a) ((a) >= '0' && (a) <= '9')
|
||||
|
||||
|
||||
#if !HAVE_FOPENCOOKIE
|
||||
/* Provide structure for our dummy replacement function. Usually this
|
||||
is defined in ../common/util.h but assuan should be self
|
||||
contained. */
|
||||
/* Fixme: Remove fopencoookie :-(( */
|
||||
typedef struct
|
||||
{
|
||||
ssize_t (*read)(void*,char*,size_t);
|
||||
ssize_t (*write)(void*,const char*,size_t);
|
||||
int (*seek)(void*,off_t*,int);
|
||||
int (*close)(void*);
|
||||
} _IO_cookie_io_functions_t;
|
||||
typedef _IO_cookie_io_functions_t cookie_io_functions_t;
|
||||
FILE *fopencookie (void *cookie, const char *opentype,
|
||||
cookie_io_functions_t funclist);
|
||||
#endif /*!HAVE_FOPENCOOKIE*/
|
||||
|
||||
|
||||
|
||||
|
||||
static int
|
||||
dummy_handler (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
return set_error (ctx, Server_Fault, "no handler registered");
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
std_handler_nop (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
return 0; /* okay */
|
||||
}
|
||||
|
||||
static int
|
||||
std_handler_cancel (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
if (ctx->cancel_notify_fnc)
|
||||
ctx->cancel_notify_fnc (ctx);
|
||||
return set_error (ctx, Not_Implemented, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
std_handler_option (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
char *key, *value, *p;
|
||||
|
||||
for (key=line; spacep (key); key++)
|
||||
;
|
||||
if (!*key)
|
||||
return set_error (ctx, Syntax_Error, "argument required");
|
||||
if (*key == '=')
|
||||
return set_error (ctx, Syntax_Error, "no option name given");
|
||||
for (value=key; *value && !spacep (value) && *value != '='; value++)
|
||||
;
|
||||
if (*value)
|
||||
{
|
||||
if (spacep (value))
|
||||
*value++ = 0; /* terminate key */
|
||||
for (; spacep (value); value++)
|
||||
;
|
||||
if (*value == '=')
|
||||
{
|
||||
*value++ = 0; /* terminate key */
|
||||
for (; spacep (value); value++)
|
||||
;
|
||||
if (!*value)
|
||||
return set_error (ctx, Syntax_Error, "option argument expected");
|
||||
}
|
||||
if (*value)
|
||||
{
|
||||
for (p = value + strlen(value) - 1; p > value && spacep (p); p--)
|
||||
;
|
||||
if (p > value)
|
||||
*++p = 0; /* strip trailing spaces */
|
||||
}
|
||||
}
|
||||
|
||||
if (*key == '-' && key[1] == '-' && key[2])
|
||||
key += 2; /* the double dashes are optional */
|
||||
if (*key == '-')
|
||||
return set_error (ctx, Syntax_Error,
|
||||
"option should not begin with one dash");
|
||||
|
||||
if (ctx->option_handler_fnc)
|
||||
return ctx->option_handler_fnc (ctx, key, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
std_handler_bye (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
if (ctx->bye_notify_fnc)
|
||||
ctx->bye_notify_fnc (ctx);
|
||||
assuan_close_input_fd (ctx);
|
||||
assuan_close_output_fd (ctx);
|
||||
return -1; /* pretty simple :-) */
|
||||
}
|
||||
|
||||
static int
|
||||
std_handler_auth (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
return set_error (ctx, Not_Implemented, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
std_handler_reset (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
if (ctx->reset_notify_fnc)
|
||||
ctx->reset_notify_fnc (ctx);
|
||||
assuan_close_input_fd (ctx);
|
||||
assuan_close_output_fd (ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
std_handler_end (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
return set_error (ctx, Not_Implemented, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
parse_cmd_input_output (ASSUAN_CONTEXT ctx, char *line, int *rfd)
|
||||
{
|
||||
char *endp;
|
||||
|
||||
if (strncmp (line, "FD=", 3))
|
||||
return set_error (ctx, Syntax_Error, "FD=<n> expected");
|
||||
line += 3;
|
||||
if (!digitp (*line))
|
||||
return set_error (ctx, Syntax_Error, "number required");
|
||||
*rfd = strtoul (line, &endp, 10);
|
||||
/* remove that argument so that a notify handler won't see it */
|
||||
memset (line, ' ', endp? (endp-line):strlen(line));
|
||||
|
||||
if (*rfd == ctx->inbound.fd)
|
||||
return set_error (ctx, Parameter_Conflict, "fd same as inbound fd");
|
||||
if (*rfd == ctx->outbound.fd)
|
||||
return set_error (ctx, Parameter_Conflict, "fd same as outbound fd");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Format is INPUT FD=<n> */
|
||||
static int
|
||||
std_handler_input (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
int rc, fd;
|
||||
|
||||
rc = parse_cmd_input_output (ctx, line, &fd);
|
||||
if (rc)
|
||||
return rc;
|
||||
ctx->input_fd = fd;
|
||||
if (ctx->input_notify_fnc)
|
||||
ctx->input_notify_fnc (ctx, line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Format is OUTPUT FD=<n> */
|
||||
static int
|
||||
std_handler_output (ASSUAN_CONTEXT ctx, char *line)
|
||||
{
|
||||
int rc, fd;
|
||||
|
||||
rc = parse_cmd_input_output (ctx, line, &fd);
|
||||
if (rc)
|
||||
return rc;
|
||||
ctx->output_fd = fd;
|
||||
if (ctx->output_notify_fnc)
|
||||
ctx->output_notify_fnc (ctx, line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* This is a table with the standard commands and handler for them.
|
||||
The table is used to initialize a new context and assuciate strings
|
||||
and handlers with cmd_ids */
|
||||
static struct {
|
||||
const char *name;
|
||||
int cmd_id;
|
||||
int (*handler)(ASSUAN_CONTEXT, char *line);
|
||||
int always; /* always initialize this command */
|
||||
} std_cmd_table[] = {
|
||||
{ "NOP", ASSUAN_CMD_NOP, std_handler_nop, 1 },
|
||||
{ "CANCEL", ASSUAN_CMD_CANCEL, std_handler_cancel, 1 },
|
||||
{ "OPTION", ASSUAN_CMD_OPTION, std_handler_option, 1 },
|
||||
{ "BYE", ASSUAN_CMD_BYE, std_handler_bye, 1 },
|
||||
{ "AUTH", ASSUAN_CMD_AUTH, std_handler_auth, 1 },
|
||||
{ "RESET", ASSUAN_CMD_RESET, std_handler_reset, 1 },
|
||||
{ "END", ASSUAN_CMD_END, std_handler_end, 1 },
|
||||
|
||||
{ "INPUT", ASSUAN_CMD_INPUT, std_handler_input },
|
||||
{ "OUTPUT", ASSUAN_CMD_OUTPUT, std_handler_output },
|
||||
{ "OPTION", ASSUAN_CMD_OPTION, std_handler_option, 1 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* assuan_register_command:
|
||||
* @ctx: the server context
|
||||
* @cmd_id: An ID value for the command
|
||||
* @cmd_name: A string with the command name
|
||||
* @handler: The handler function to be called
|
||||
*
|
||||
* Register a handler to be used for a given command.
|
||||
*
|
||||
* The @cmd_name must be %NULL or an empty string for all @cmd_ids
|
||||
* below %ASSUAN_CMD_USER because predefined values are used.
|
||||
*
|
||||
* Return value:
|
||||
**/
|
||||
int
|
||||
assuan_register_command (ASSUAN_CONTEXT ctx,
|
||||
int cmd_id, const char *cmd_name,
|
||||
int (*handler)(ASSUAN_CONTEXT, char *))
|
||||
{
|
||||
int i;
|
||||
|
||||
if (cmd_name && !*cmd_name)
|
||||
cmd_name = NULL;
|
||||
|
||||
if (cmd_id < ASSUAN_CMD_USER)
|
||||
{
|
||||
if (cmd_name)
|
||||
return ASSUAN_Invalid_Value; /* must be NULL for these values*/
|
||||
|
||||
for (i=0; std_cmd_table[i].name; i++)
|
||||
{
|
||||
if (std_cmd_table[i].cmd_id == cmd_id)
|
||||
{
|
||||
cmd_name = std_cmd_table[i].name;
|
||||
if (!handler)
|
||||
handler = std_cmd_table[i].handler;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!std_cmd_table[i].name)
|
||||
return ASSUAN_Invalid_Value; /* not a pre-registered one */
|
||||
}
|
||||
|
||||
if (!handler)
|
||||
handler = dummy_handler;
|
||||
|
||||
if (!cmd_name)
|
||||
return ASSUAN_Invalid_Value;
|
||||
|
||||
/* fprintf (stderr, "DBG-assuan: registering %d as `%s'\n", cmd_id, cmd_name); */
|
||||
|
||||
if (!ctx->cmdtbl)
|
||||
{
|
||||
ctx->cmdtbl_size = 50;
|
||||
ctx->cmdtbl = xtrycalloc ( ctx->cmdtbl_size, sizeof *ctx->cmdtbl);
|
||||
if (!ctx->cmdtbl)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
ctx->cmdtbl_used = 0;
|
||||
}
|
||||
else if (ctx->cmdtbl_used >= ctx->cmdtbl_size)
|
||||
{
|
||||
struct cmdtbl_s *x;
|
||||
|
||||
x = xtryrealloc ( ctx->cmdtbl, (ctx->cmdtbl_size+10) * sizeof *x);
|
||||
if (!x)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
ctx->cmdtbl = x;
|
||||
ctx->cmdtbl_size += 50;
|
||||
}
|
||||
|
||||
ctx->cmdtbl[ctx->cmdtbl_used].name = cmd_name;
|
||||
ctx->cmdtbl[ctx->cmdtbl_used].cmd_id = cmd_id;
|
||||
ctx->cmdtbl[ctx->cmdtbl_used].handler = handler;
|
||||
ctx->cmdtbl_used++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
assuan_register_bye_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
|
||||
{
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
ctx->bye_notify_fnc = fnc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
assuan_register_reset_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
|
||||
{
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
ctx->reset_notify_fnc = fnc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
assuan_register_cancel_notify (ASSUAN_CONTEXT ctx, void (*fnc)(ASSUAN_CONTEXT))
|
||||
{
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
ctx->cancel_notify_fnc = fnc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
assuan_register_option_handler (ASSUAN_CONTEXT ctx,
|
||||
int (*fnc)(ASSUAN_CONTEXT,
|
||||
const char*, const char*))
|
||||
{
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
ctx->option_handler_fnc = fnc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
assuan_register_input_notify (ASSUAN_CONTEXT ctx,
|
||||
void (*fnc)(ASSUAN_CONTEXT, const char *))
|
||||
{
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
ctx->input_notify_fnc = fnc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
assuan_register_output_notify (ASSUAN_CONTEXT ctx,
|
||||
void (*fnc)(ASSUAN_CONTEXT, const char *))
|
||||
{
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
ctx->output_notify_fnc = fnc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Helper to register the standards commands */
|
||||
int
|
||||
_assuan_register_std_commands (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
int i, rc;
|
||||
|
||||
for (i=0; std_cmd_table[i].name; i++)
|
||||
{
|
||||
if (std_cmd_table[i].always)
|
||||
{
|
||||
rc = assuan_register_command (ctx, std_cmd_table[i].cmd_id,
|
||||
NULL, NULL);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Process the special data lines. The "D " has already been removed
|
||||
from the line. As all handlers this function may modify the line. */
|
||||
static int
|
||||
handle_data_line (ASSUAN_CONTEXT ctx, char *line, int linelen)
|
||||
{
|
||||
return set_error (ctx, Not_Implemented, NULL);
|
||||
}
|
||||
|
||||
/* like ascii_strcasecmp but assume that B is already uppercase */
|
||||
static int
|
||||
my_strcasecmp (const char *a, const char *b)
|
||||
{
|
||||
if (a == b)
|
||||
return 0;
|
||||
|
||||
for (; *a && *b; a++, b++)
|
||||
{
|
||||
if (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) != *b)
|
||||
break;
|
||||
}
|
||||
return *a == *b? 0 : (((*a >= 'a' && *a <= 'z')? (*a&~0x20):*a) - *b);
|
||||
}
|
||||
|
||||
/* Parse the line, break out the command, find it in the command
|
||||
table, remove leading and white spaces from the arguments, all the
|
||||
handler with the argument line and return the error */
|
||||
static int
|
||||
dispatch_command (ASSUAN_CONTEXT ctx, char *line, int linelen)
|
||||
{
|
||||
char *p;
|
||||
const char *s;
|
||||
int shift, i;
|
||||
|
||||
if (*line == 'D' && line[1] == ' ') /* divert to special handler */
|
||||
return handle_data_line (ctx, line+2, linelen-2);
|
||||
|
||||
for (p=line; *p && *p != ' ' && *p != '\t'; p++)
|
||||
;
|
||||
if (p==line)
|
||||
return set_error (ctx, Invalid_Command, "leading white-space");
|
||||
if (*p)
|
||||
{ /* Skip over leading WS after the keyword */
|
||||
*p++ = 0;
|
||||
while ( *p == ' ' || *p == '\t')
|
||||
p++;
|
||||
}
|
||||
shift = p - line;
|
||||
|
||||
for (i=0; (s=ctx->cmdtbl[i].name); i++)
|
||||
{
|
||||
if (!strcmp (line, s))
|
||||
break;
|
||||
}
|
||||
if (!s)
|
||||
{ /* and try case insensitive */
|
||||
for (i=0; (s=ctx->cmdtbl[i].name); i++)
|
||||
{
|
||||
if (!my_strcasecmp (line, s))
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!s)
|
||||
return set_error (ctx, Unknown_Command, NULL);
|
||||
line += shift;
|
||||
linelen -= shift;
|
||||
|
||||
/* fprintf (stderr, "DBG-assuan: processing %s `%s'\n", s, line); */
|
||||
return ctx->cmdtbl[i].handler (ctx, line);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int
|
||||
process_request (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (ctx->in_inquire)
|
||||
return ASSUAN_Nested_Commands;
|
||||
|
||||
rc = _assuan_read_line (ctx);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (*ctx->inbound.line == '#' || !ctx->inbound.linelen)
|
||||
return 0; /* comment line - ignore */
|
||||
|
||||
ctx->outbound.data.error = 0;
|
||||
ctx->outbound.data.linelen = 0;
|
||||
/* dispatch command and return reply */
|
||||
rc = dispatch_command (ctx, ctx->inbound.line, ctx->inbound.linelen);
|
||||
/* check from data write errors */
|
||||
if (ctx->outbound.data.fp)
|
||||
{ /* Flush the data lines */
|
||||
fclose (ctx->outbound.data.fp);
|
||||
ctx->outbound.data.fp = NULL;
|
||||
if (!rc && ctx->outbound.data.error)
|
||||
rc = ctx->outbound.data.error;
|
||||
}
|
||||
else /* flush any data send w/o using the data fp */
|
||||
{
|
||||
assuan_send_data (ctx, NULL, 0);
|
||||
if (!rc && ctx->outbound.data.error)
|
||||
rc = ctx->outbound.data.error;
|
||||
}
|
||||
/* Error handling */
|
||||
if (!rc)
|
||||
{
|
||||
rc = assuan_write_line (ctx, ctx->okay_line? ctx->okay_line : "OK");
|
||||
}
|
||||
else if (rc == -1)
|
||||
{ /* No error checking because the peer may have already disconnect */
|
||||
assuan_write_line (ctx, "OK closing connection");
|
||||
ctx->finish_handler (ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
char errline[256];
|
||||
|
||||
if (rc < 100)
|
||||
sprintf (errline, "ERR %d server fault (%.50s)",
|
||||
ASSUAN_Server_Fault, assuan_strerror (rc));
|
||||
else
|
||||
{
|
||||
const char *text = ctx->err_no == rc? ctx->err_str:NULL;
|
||||
|
||||
sprintf (errline, "ERR %d %.50s%s%.100s",
|
||||
rc, assuan_strerror (rc), text? " - ":"", text?text:"");
|
||||
}
|
||||
rc = assuan_write_line (ctx, errline);
|
||||
}
|
||||
|
||||
ctx->confidential = 0;
|
||||
if (ctx->okay_line)
|
||||
{
|
||||
xfree (ctx->okay_line);
|
||||
ctx->okay_line = NULL;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* assuan_process:
|
||||
* @ctx: assuan context
|
||||
*
|
||||
* This fucntion is used to handle the assuan protocol after a
|
||||
* connection has been established using assuan_accept(). This is the
|
||||
* main protocol handler.
|
||||
*
|
||||
* Return value: 0 on success or an error code if the assuan operation
|
||||
* failed. Note, that no error is returned for operational errors.
|
||||
**/
|
||||
int
|
||||
assuan_process (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
int rc;
|
||||
|
||||
do {
|
||||
rc = process_request (ctx);
|
||||
} while (!rc);
|
||||
|
||||
if (rc == -1)
|
||||
rc = 0;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* assuan_process_next:
|
||||
* @ctx: Assuan context
|
||||
*
|
||||
* Same as assuan_process() but the user has to provide the outer
|
||||
* loop. He should loop as long as the return code is zero and stop
|
||||
* otherwise; -1 is regular end.
|
||||
*
|
||||
* See also: assuan_get_active_fds()
|
||||
* Return value: -1 for end of server, 0 on success or an error code
|
||||
**/
|
||||
int
|
||||
assuan_process_next (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
return process_request (ctx);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* assuan_get_active_fds:
|
||||
* @ctx: Assuan context
|
||||
* @what: 0 for read fds, 1 for write fds
|
||||
* @fdarray: Caller supplied array to store the FDs
|
||||
* @fdarraysize: size of that array
|
||||
*
|
||||
* Return all active filedescriptors for the given context. This
|
||||
* function can be used to select on the fds and call
|
||||
* assuan_process_next() if there is an active one. The first fd in
|
||||
* the array is the one used for the command connection.
|
||||
*
|
||||
* Note, that write FDs are not yet supported.
|
||||
*
|
||||
* Return value: number of FDs active and put into @fdarray or -1 on
|
||||
* error which is most likely a too small fdarray.
|
||||
**/
|
||||
int
|
||||
assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what,
|
||||
int *fdarray, int fdarraysize)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
if (!ctx || fdarraysize < 2 || what < 0 || what > 1)
|
||||
return -1;
|
||||
|
||||
if (!what)
|
||||
{
|
||||
if (ctx->inbound.fd != -1)
|
||||
fdarray[n++] = ctx->inbound.fd;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ctx->outbound.fd != -1)
|
||||
fdarray[n++] = ctx->outbound.fd;
|
||||
if (ctx->outbound.data.fp)
|
||||
fdarray[n++] = fileno (ctx->outbound.data.fp);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/* Return a FP to be used for data output. The FILE pointer is valid
|
||||
until the end of a handler. So a close is not needed. Assuan does
|
||||
all the buffering needed to insert the status line as well as the
|
||||
required line wappping and quoting for data lines.
|
||||
|
||||
We use GNU's custom streams here. There should be an alternative
|
||||
implementaion for systems w/o a glibc, a simple implementation
|
||||
could use a child process */
|
||||
FILE *
|
||||
assuan_get_data_fp (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
cookie_io_functions_t cookie_fnc;
|
||||
|
||||
if (ctx->outbound.data.fp)
|
||||
return ctx->outbound.data.fp;
|
||||
|
||||
cookie_fnc.read = NULL;
|
||||
cookie_fnc.write = _assuan_cookie_write_data;
|
||||
cookie_fnc.seek = NULL;
|
||||
cookie_fnc.close = _assuan_cookie_write_flush;
|
||||
|
||||
ctx->outbound.data.fp = fopencookie (ctx, "wb", cookie_fnc);
|
||||
ctx->outbound.data.error = 0;
|
||||
return ctx->outbound.data.fp;
|
||||
}
|
||||
|
||||
|
||||
/* Set the text used for the next OK reponse. This string is
|
||||
automatically reset to NULL after the next command. */
|
||||
AssuanError
|
||||
assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line)
|
||||
{
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
if (!line)
|
||||
{
|
||||
xfree (ctx->okay_line);
|
||||
ctx->okay_line = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: we need to use gcry_is_secure() to test whether
|
||||
we should allocate the entire line in secure memory */
|
||||
char *buf = xtrymalloc (3+strlen(line)+1);
|
||||
if (!buf)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
strcpy (buf, "OK ");
|
||||
strcpy (buf+3, line);
|
||||
xfree (ctx->okay_line);
|
||||
ctx->okay_line = buf;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
assuan_write_status (ASSUAN_CONTEXT ctx, const char *keyword, const char *text)
|
||||
{
|
||||
char buffer[256];
|
||||
char *helpbuf;
|
||||
size_t n;
|
||||
|
||||
if ( !ctx || !keyword)
|
||||
return;
|
||||
if (!text)
|
||||
text = "";
|
||||
|
||||
n = 2 + strlen (keyword) + 1 + strlen (text) + 1;
|
||||
if (n < sizeof (buffer))
|
||||
{
|
||||
strcpy (buffer, "S ");
|
||||
strcat (buffer, keyword);
|
||||
if (*text)
|
||||
{
|
||||
strcat (buffer, " ");
|
||||
strcat (buffer, text);
|
||||
}
|
||||
assuan_write_line (ctx, buffer);
|
||||
}
|
||||
else if ( (helpbuf = xtrymalloc (n)) )
|
||||
{
|
||||
strcpy (helpbuf, "S ");
|
||||
strcat (helpbuf, keyword);
|
||||
if (*text)
|
||||
{
|
||||
strcat (helpbuf, " ");
|
||||
strcat (helpbuf, text);
|
||||
}
|
||||
assuan_write_line (ctx, helpbuf);
|
||||
xfree (helpbuf);
|
||||
}
|
||||
}
|
@ -1,239 +0,0 @@
|
||||
/* assuan-inquire.c - handle inquire stuff
|
||||
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of Assuan.
|
||||
*
|
||||
* Assuan is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Assuan 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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 <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "assuan-defs.h"
|
||||
|
||||
#define digitp(a) ((a) >= '0' && (a) <= '9')
|
||||
#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
|
||||
*(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
|
||||
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
|
||||
|
||||
|
||||
struct membuf {
|
||||
size_t len;
|
||||
size_t size;
|
||||
char *buf;
|
||||
int out_of_core;
|
||||
int too_large;
|
||||
size_t maxlen;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* A simple implemnation of a dynamic buffer. Use init_membuf() to
|
||||
create a buffer, put_membuf to append bytes and get_membuf to
|
||||
release and return the buffer. Allocation errors are detected but
|
||||
only returned at the final get_membuf(), this helps not to clutter
|
||||
the code with out of core checks. */
|
||||
|
||||
static void
|
||||
init_membuf (struct membuf *mb, int initiallen, size_t maxlen)
|
||||
{
|
||||
mb->len = 0;
|
||||
mb->size = initiallen;
|
||||
mb->out_of_core = 0;
|
||||
mb->too_large = 0;
|
||||
mb->maxlen = maxlen;
|
||||
/* we need to allocate one byte more for get_membuf */
|
||||
mb->buf = xtrymalloc (initiallen+1);
|
||||
if (!mb->buf)
|
||||
mb->out_of_core = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
put_membuf (struct membuf *mb, const void *buf, size_t len)
|
||||
{
|
||||
if (mb->out_of_core || mb->too_large)
|
||||
return;
|
||||
|
||||
if (mb->maxlen && mb->len + len > mb->maxlen)
|
||||
{
|
||||
mb->too_large = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mb->len + len >= mb->size)
|
||||
{
|
||||
char *p;
|
||||
|
||||
mb->size += len + 1024;
|
||||
/* we need to allocate one byte more for get_membuf */
|
||||
p = xtryrealloc (mb->buf, mb->size+1);
|
||||
if (!p)
|
||||
{
|
||||
mb->out_of_core = 1;
|
||||
return;
|
||||
}
|
||||
mb->buf = p;
|
||||
}
|
||||
memcpy (mb->buf + mb->len, buf, len);
|
||||
mb->len += len;
|
||||
}
|
||||
|
||||
static void *
|
||||
get_membuf (struct membuf *mb, size_t *len)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (mb->out_of_core || mb->too_large)
|
||||
{
|
||||
xfree (mb->buf);
|
||||
mb->buf = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mb->buf[mb->len] = 0; /* there is enough space for the hidden eos */
|
||||
p = mb->buf;
|
||||
*len = mb->len;
|
||||
mb->buf = NULL;
|
||||
mb->out_of_core = 1; /* don't allow a reuse */
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
free_membuf (struct membuf *mb)
|
||||
{
|
||||
xfree (mb->buf);
|
||||
mb->buf = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* assuan_inquire:
|
||||
* @ctx: An assuan context
|
||||
* @keyword: The keyword used for the inquire
|
||||
* @r_buffer: Returns an allocated buffer
|
||||
* @r_length: Returns the length of this buffer
|
||||
* @maxlen: If not 0, the size limit of the inquired data.
|
||||
*
|
||||
* A Server may use this to Send an inquire. r_buffer, r_length and
|
||||
* maxlen may all be NULL/0 to indicate that no real data is expected.
|
||||
*
|
||||
* Return value: 0 on success or an ASSUAN error code
|
||||
**/
|
||||
AssuanError
|
||||
assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword,
|
||||
char **r_buffer, size_t *r_length, size_t maxlen)
|
||||
{
|
||||
AssuanError rc;
|
||||
struct membuf mb;
|
||||
char cmdbuf[100];
|
||||
unsigned char *line, *p;
|
||||
int linelen;
|
||||
int nodataexpected;
|
||||
|
||||
if (!ctx || !keyword || (10 + strlen (keyword) >= sizeof (cmdbuf)))
|
||||
return ASSUAN_Invalid_Value;
|
||||
nodataexpected = !r_buffer && !r_length && !maxlen;
|
||||
if (!nodataexpected && (!r_buffer || !r_length))
|
||||
return ASSUAN_Invalid_Value;
|
||||
if (!ctx->is_server)
|
||||
return ASSUAN_Not_A_Server;
|
||||
if (ctx->in_inquire)
|
||||
return ASSUAN_Nested_Commands;
|
||||
|
||||
ctx->in_inquire = 1;
|
||||
if (nodataexpected)
|
||||
memset (&mb, 0, sizeof mb); /* avoid compiler warnings */
|
||||
else
|
||||
init_membuf (&mb, maxlen? maxlen:1024, maxlen);
|
||||
|
||||
strcpy (stpcpy (cmdbuf, "INQUIRE "), keyword);
|
||||
rc = assuan_write_line (ctx, cmdbuf);
|
||||
if (rc)
|
||||
goto leave;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
do
|
||||
{
|
||||
rc = _assuan_read_line (ctx);
|
||||
if (rc)
|
||||
goto leave;
|
||||
line = ctx->inbound.line;
|
||||
linelen = ctx->inbound.linelen;
|
||||
}
|
||||
while (*line == '#' || !linelen);
|
||||
if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D'
|
||||
&& (!line[3] || line[3] == ' '))
|
||||
break; /* END command received*/
|
||||
if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N')
|
||||
{
|
||||
rc = ASSUAN_Canceled;
|
||||
goto leave;
|
||||
}
|
||||
if (line[0] != 'D' || line[1] != ' ' || nodataexpected)
|
||||
{
|
||||
rc = ASSUAN_Unexpected_Command;
|
||||
goto leave;
|
||||
}
|
||||
if (linelen < 3)
|
||||
continue;
|
||||
line += 2;
|
||||
linelen -= 2;
|
||||
|
||||
p = line;
|
||||
while (linelen)
|
||||
{
|
||||
for (;linelen && *p != '%'; linelen--, p++)
|
||||
;
|
||||
put_membuf (&mb, line, p-line);
|
||||
if (linelen > 2)
|
||||
{ /* handle escaping */
|
||||
unsigned char tmp[1];
|
||||
p++;
|
||||
*tmp = xtoi_2 (p);
|
||||
p += 2;
|
||||
linelen -= 3;
|
||||
put_membuf (&mb, tmp, 1);
|
||||
}
|
||||
line = p;
|
||||
}
|
||||
if (mb.too_large)
|
||||
{
|
||||
rc = ASSUAN_Too_Much_Data;
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nodataexpected)
|
||||
{
|
||||
*r_buffer = get_membuf (&mb, r_length);
|
||||
if (!*r_buffer)
|
||||
rc = ASSUAN_Out_Of_Core;
|
||||
}
|
||||
|
||||
leave:
|
||||
if (!nodataexpected)
|
||||
free_membuf (&mb);
|
||||
ctx->in_inquire = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,132 +0,0 @@
|
||||
/* assuan-listen.c - Wait for a connection (server)
|
||||
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of Assuan.
|
||||
*
|
||||
* Assuan is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Assuan 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "assuan-defs.h"
|
||||
|
||||
AssuanError
|
||||
assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line)
|
||||
{
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
if (!line)
|
||||
{
|
||||
xfree (ctx->hello_line);
|
||||
ctx->hello_line = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *buf = xtrymalloc (3+strlen(line)+1);
|
||||
if (!buf)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
strcpy (buf, "OK ");
|
||||
strcpy (buf+3, line);
|
||||
xfree (ctx->hello_line);
|
||||
ctx->hello_line = buf;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* assuan_accept:
|
||||
* @ctx: context
|
||||
*
|
||||
* Cancel any existing connectiion and wait for a connection from a
|
||||
* client. The initial handshake is performed which may include an
|
||||
* initial authentication or encryption negotiation.
|
||||
*
|
||||
* Return value: 0 on success or an error if the connection could for
|
||||
* some reason not be established.
|
||||
**/
|
||||
AssuanError
|
||||
assuan_accept (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!ctx)
|
||||
return ASSUAN_Invalid_Value;
|
||||
|
||||
if (ctx->pipe_mode > 1)
|
||||
return -1; /* second invocation for pipemode -> terminate */
|
||||
ctx->finish_handler (ctx);
|
||||
|
||||
rc = ctx->accept_handler (ctx);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* send the hello */
|
||||
rc = assuan_write_line (ctx, ctx->hello_line? ctx->hello_line
|
||||
: "OK Your orders please");
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (ctx->pipe_mode)
|
||||
ctx->pipe_mode = 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
assuan_get_input_fd (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
return ctx? ctx->input_fd : -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
assuan_get_output_fd (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
return ctx? ctx->output_fd : -1;
|
||||
}
|
||||
|
||||
|
||||
/* Close the fd descriptor set by the command INPUT FD=n. We handle
|
||||
this fd inside assuan so that we can do some initial checks */
|
||||
AssuanError
|
||||
assuan_close_input_fd (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
if (!ctx || ctx->input_fd == -1)
|
||||
return ASSUAN_Invalid_Value;
|
||||
close (ctx->input_fd);
|
||||
ctx->input_fd = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Close the fd descriptor set by the command OUTPUT FD=n. We handle
|
||||
this fd inside assuan so that we can do some initial checks */
|
||||
AssuanError
|
||||
assuan_close_output_fd (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
if (!ctx || ctx->output_fd == -1)
|
||||
return ASSUAN_Invalid_Value;
|
||||
|
||||
close (ctx->output_fd);
|
||||
ctx->output_fd = -1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,288 +0,0 @@
|
||||
/* assuan-pipe-connect.c - Establish a pipe connection (client)
|
||||
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of Assuan.
|
||||
*
|
||||
* Assuan is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Assuan 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "assuan-defs.h"
|
||||
|
||||
#ifdef _POSIX_OPEN_MAX
|
||||
#define MAX_OPEN_FDS _POSIX_OPEN_MAX
|
||||
#else
|
||||
#define MAX_OPEN_FDS 20
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_JNLIB_LOGGING
|
||||
#include "../jnlib/logging.h"
|
||||
#define LOGERROR1(a,b) log_error ((a), (b))
|
||||
#else
|
||||
#define LOGERROR1(a,b) fprintf (stderr, (a), (b))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static int
|
||||
writen ( int fd, const char *buffer, size_t length )
|
||||
{
|
||||
while (length)
|
||||
{
|
||||
int nwritten = write (fd, buffer, length);
|
||||
|
||||
if (nwritten < 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return -1; /* write error */
|
||||
}
|
||||
length -= nwritten;
|
||||
buffer += nwritten;
|
||||
}
|
||||
return 0; /* okay */
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_finish (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
if (ctx->inbound.fd != -1)
|
||||
{
|
||||
close (ctx->inbound.fd);
|
||||
ctx->inbound.fd = -1;
|
||||
}
|
||||
if (ctx->outbound.fd != -1)
|
||||
{
|
||||
close (ctx->outbound.fd);
|
||||
ctx->outbound.fd = -1;
|
||||
}
|
||||
if (ctx->pid != -1)
|
||||
{
|
||||
waitpid (ctx->pid, NULL, 0); /* FIXME Check return value. */
|
||||
ctx->pid = -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
do_deinit (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
do_finish (ctx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Connect to a server over a pipe, creating the assuan context and
|
||||
returning it in CTX. The server filename is NAME, the argument
|
||||
vector in ARGV. FD_CHILD_LIST is a -1 terminated list of file
|
||||
descriptors not to close in the child. */
|
||||
AssuanError
|
||||
assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name, char *const argv[],
|
||||
int *fd_child_list)
|
||||
{
|
||||
static int fixed_signals = 0;
|
||||
AssuanError err;
|
||||
int rp[2];
|
||||
int wp[2];
|
||||
|
||||
if (!ctx || !name || !argv || !argv[0])
|
||||
return ASSUAN_Invalid_Value;
|
||||
|
||||
if (!fixed_signals)
|
||||
{
|
||||
struct sigaction act;
|
||||
|
||||
sigaction (SIGPIPE, NULL, &act);
|
||||
if (act.sa_handler == SIG_DFL)
|
||||
{
|
||||
act.sa_handler = SIG_IGN;
|
||||
sigemptyset (&act.sa_mask);
|
||||
act.sa_flags = 0;
|
||||
sigaction (SIGPIPE, &act, NULL);
|
||||
}
|
||||
fixed_signals = 1;
|
||||
/* FIXME: This is not MT safe */
|
||||
}
|
||||
|
||||
if (pipe (rp) < 0)
|
||||
return ASSUAN_General_Error;
|
||||
|
||||
if (pipe (wp) < 0)
|
||||
{
|
||||
close (rp[0]);
|
||||
close (rp[1]);
|
||||
return ASSUAN_General_Error;
|
||||
}
|
||||
|
||||
err = _assuan_new_context (ctx);
|
||||
if (err)
|
||||
{
|
||||
close (rp[0]);
|
||||
close (rp[1]);
|
||||
close (wp[0]);
|
||||
close (wp[1]);
|
||||
return err;
|
||||
}
|
||||
(*ctx)->pipe_mode = 1;
|
||||
(*ctx)->inbound.fd = rp[0]; /* Our inbound is read end of read pipe. */
|
||||
(*ctx)->outbound.fd = wp[1]; /* Our outbound is write end of write pipe. */
|
||||
(*ctx)->deinit_handler = do_deinit;
|
||||
(*ctx)->finish_handler = do_finish;
|
||||
|
||||
(*ctx)->pid = fork ();
|
||||
if ((*ctx)->pid < 0)
|
||||
{
|
||||
close (rp[0]);
|
||||
close (rp[1]);
|
||||
close (wp[0]);
|
||||
close (wp[1]);
|
||||
_assuan_release_context (*ctx);
|
||||
return ASSUAN_General_Error;
|
||||
}
|
||||
|
||||
if ((*ctx)->pid == 0)
|
||||
{
|
||||
int i, n;
|
||||
char errbuf[512];
|
||||
int *fdp;
|
||||
|
||||
/* Close all files which will not be duped and are not in the
|
||||
fd_child_list. */
|
||||
n = sysconf (_SC_OPEN_MAX);
|
||||
if (n < 0)
|
||||
n = MAX_OPEN_FDS;
|
||||
for (i=0; i < n; i++)
|
||||
{
|
||||
fdp = fd_child_list;
|
||||
if (fdp)
|
||||
{
|
||||
while (*fdp != -1 && *fdp != i)
|
||||
fdp++;
|
||||
}
|
||||
|
||||
if (!(fdp && *fdp != -1)
|
||||
&& i != rp[1] && i != wp[0])
|
||||
close(i);
|
||||
}
|
||||
errno = 0;
|
||||
|
||||
/* Dup stderr to /dev/null unless it is in the list of FDs to be
|
||||
passed to the child. */
|
||||
fdp = fd_child_list;
|
||||
if (fdp)
|
||||
{
|
||||
for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++)
|
||||
;
|
||||
}
|
||||
if (!fdp || *fdp == -1)
|
||||
{
|
||||
int fd = open ("/dev/null", O_WRONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
LOGERROR1 ("can't open `/dev/null': %s\n", strerror (errno));
|
||||
_exit (4);
|
||||
}
|
||||
if (dup2 (fd, STDERR_FILENO) == -1)
|
||||
{
|
||||
LOGERROR1 ("dup2(dev/null, 2) failed: %s\n", strerror (errno));
|
||||
_exit (4);
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
|
||||
/* Dup handles and to stdin/stdout and exec. */
|
||||
if (rp[1] != STDOUT_FILENO)
|
||||
{
|
||||
if (dup2 (rp[1], STDOUT_FILENO) == -1)
|
||||
{
|
||||
LOGERROR1 ("dup2 failed in child: %s\n", strerror (errno));
|
||||
_exit (4);
|
||||
}
|
||||
close (rp[1]);
|
||||
}
|
||||
if (wp[0] != STDIN_FILENO)
|
||||
{
|
||||
if (dup2 (wp[0], STDIN_FILENO) == -1)
|
||||
{
|
||||
LOGERROR1 ("dup2 failed in child: %s\n", strerror (errno));
|
||||
_exit (4);
|
||||
}
|
||||
close (wp[0]);
|
||||
}
|
||||
|
||||
execv (name, argv);
|
||||
/* oops - use the pipe to tell the parent about it */
|
||||
snprintf (errbuf, sizeof(errbuf)-1, "ERR %d can't exec `%s': %.50s\n",
|
||||
ASSUAN_Problem_Starting_Server, name, strerror (errno));
|
||||
errbuf[sizeof(errbuf)-1] = 0;
|
||||
writen (1, errbuf, strlen (errbuf));
|
||||
_exit (4);
|
||||
}
|
||||
|
||||
close (rp[1]);
|
||||
close (wp[0]);
|
||||
|
||||
/* initial handshake */
|
||||
{
|
||||
int okay, off;
|
||||
|
||||
err = _assuan_read_from_server (*ctx, &okay, &off);
|
||||
if (err)
|
||||
{
|
||||
LOGERROR1 ("can't connect server: %s\n", assuan_strerror (err));
|
||||
}
|
||||
else if (okay != 1)
|
||||
{
|
||||
LOGERROR1 ("can't connect server: `%s'\n", (*ctx)->inbound.line);
|
||||
err = ASSUAN_Connect_Failed;
|
||||
}
|
||||
}
|
||||
|
||||
if (err)
|
||||
{
|
||||
assuan_disconnect (*ctx);
|
||||
*ctx = NULL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,124 +0,0 @@
|
||||
/* assuan-pipe-server.c - Assuan server working over a pipe
|
||||
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of Assuan.
|
||||
*
|
||||
* Assuan is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Assuan 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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 <stdio.h>
|
||||
|
||||
#include "assuan-defs.h"
|
||||
|
||||
static void
|
||||
deinit_pipe_server (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
/* nothing to do for this simple server */
|
||||
}
|
||||
|
||||
static int
|
||||
accept_connection (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
/* This is a NOP for a pipe server */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
finish_connection (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
/* This is a NOP for a pipe server */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Create a new context. Note that the handlers are set up for a pipe
|
||||
server/client - this way we don't need extra dummy functions */
|
||||
int
|
||||
_assuan_new_context (ASSUAN_CONTEXT *r_ctx)
|
||||
{
|
||||
ASSUAN_CONTEXT ctx;
|
||||
int rc;
|
||||
|
||||
*r_ctx = NULL;
|
||||
ctx = xtrycalloc (1, sizeof *ctx);
|
||||
if (!ctx)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
ctx->input_fd = -1;
|
||||
ctx->output_fd = -1;
|
||||
|
||||
ctx->inbound.fd = -1;
|
||||
ctx->outbound.fd = -1;
|
||||
|
||||
ctx->listen_fd = -1;
|
||||
ctx->client_pid = (pid_t)-1;
|
||||
/* use the pipe server handler as a default */
|
||||
ctx->deinit_handler = deinit_pipe_server;
|
||||
ctx->accept_handler = accept_connection;
|
||||
ctx->finish_handler = finish_connection;
|
||||
|
||||
rc = _assuan_register_std_commands (ctx);
|
||||
if (rc)
|
||||
xfree (ctx);
|
||||
else
|
||||
*r_ctx = ctx;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2])
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = _assuan_new_context (r_ctx);
|
||||
if (!rc)
|
||||
{
|
||||
ASSUAN_CONTEXT ctx = *r_ctx;
|
||||
|
||||
ctx->is_server = 1;
|
||||
ctx->inbound.fd = filedes[0];
|
||||
ctx->outbound.fd = filedes[1];
|
||||
ctx->pipe_mode = 1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_assuan_release_context (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
if (ctx)
|
||||
{
|
||||
xfree (ctx->hello_line);
|
||||
xfree (ctx->okay_line);
|
||||
xfree (ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
assuan_deinit_server (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
if (ctx)
|
||||
{
|
||||
/* We use this function pointer to avoid linking other server
|
||||
when not needed but still allow for a generic deinit function */
|
||||
ctx->deinit_handler (ctx);
|
||||
ctx->deinit_handler = NULL;
|
||||
_assuan_release_context (ctx);
|
||||
}
|
||||
}
|
@ -1,150 +0,0 @@
|
||||
/* assuan-socket-connect.c - Assuan socket based client
|
||||
* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of Assuan.
|
||||
*
|
||||
* Assuan is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Assuan 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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 <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "assuan-defs.h"
|
||||
|
||||
#ifdef HAVE_JNLIB_LOGGING
|
||||
#include "../jnlib/logging.h"
|
||||
#define LOGERROR(a) log_error ((a))
|
||||
#define LOGERROR1(a,b) log_error ((a), (b))
|
||||
#define LOGERROR2(a,b,c) log_error ((a), (b), (c))
|
||||
#define LOGERRORX(a) log_printf ((a))
|
||||
#else
|
||||
#define LOGERROR(a) fprintf (stderr, (a))
|
||||
#define LOGERROR1(a,b) fprintf (stderr, (a), (b))
|
||||
#define LOGERROR2(a,b,c) fprintf (stderr, (a), (b), (c))
|
||||
#define LOGERRORX(a) fputs ((a), stderr)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static int
|
||||
do_finish (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
if (ctx->inbound.fd != -1)
|
||||
{
|
||||
close (ctx->inbound.fd);
|
||||
}
|
||||
ctx->inbound.fd = -1;
|
||||
ctx->outbound.fd = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
do_deinit (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
do_finish (ctx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Make a connection to the Unix domain socket NAME and return a new
|
||||
Assuan context in CTX. SERVER_PID is currently not used but may
|
||||
becode handy in future. */
|
||||
AssuanError
|
||||
assuan_socket_connect (ASSUAN_CONTEXT *r_ctx,
|
||||
const char *name, pid_t server_pid)
|
||||
{
|
||||
AssuanError err;
|
||||
ASSUAN_CONTEXT ctx;
|
||||
int fd;
|
||||
struct sockaddr_un srvr_addr;
|
||||
size_t len;
|
||||
|
||||
if (!r_ctx || !name)
|
||||
return ASSUAN_Invalid_Value;
|
||||
*r_ctx = NULL;
|
||||
|
||||
/* we require that the name starts with a slash, so that we can
|
||||
alter reuse this function for other socket types */
|
||||
if (*name != '/')
|
||||
return ASSUAN_Invalid_Value;
|
||||
if (strlen (name)+1 >= sizeof srvr_addr.sun_path)
|
||||
return ASSUAN_Invalid_Value;
|
||||
|
||||
err = _assuan_new_context (&ctx);
|
||||
if (err)
|
||||
return err;
|
||||
ctx->pid = server_pid; /* save it in case we need it later */
|
||||
ctx->deinit_handler = do_deinit;
|
||||
ctx->finish_handler = do_finish;
|
||||
|
||||
fd = socket (AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd == -1)
|
||||
{
|
||||
LOGERROR1 ("can't create socket: %s\n", strerror (errno));
|
||||
_assuan_release_context (ctx);
|
||||
return ASSUAN_General_Error;
|
||||
}
|
||||
|
||||
memset (&srvr_addr, 0, sizeof srvr_addr );
|
||||
srvr_addr.sun_family = AF_UNIX;
|
||||
strcpy (srvr_addr.sun_path, name);
|
||||
len = (offsetof (struct sockaddr_un, sun_path)
|
||||
+ strlen (srvr_addr.sun_path) + 1);
|
||||
|
||||
if (connect (fd, (struct sockaddr*)&srvr_addr, len) == -1)
|
||||
{
|
||||
LOGERROR2 ("can't connect to `%s': %s\n", name, strerror (errno));
|
||||
_assuan_release_context (ctx);
|
||||
close (fd );
|
||||
return ASSUAN_Connect_Failed;
|
||||
}
|
||||
|
||||
ctx->inbound.fd = fd;
|
||||
ctx->outbound.fd = fd;
|
||||
|
||||
/* initial handshake */
|
||||
{
|
||||
int okay, off;
|
||||
|
||||
err = _assuan_read_from_server (ctx, &okay, &off);
|
||||
if (err)
|
||||
{
|
||||
LOGERROR1 ("can't connect server: %s\n", assuan_strerror (err));
|
||||
}
|
||||
else if (okay != 1)
|
||||
{
|
||||
LOGERROR ("can't connect server: `");
|
||||
_assuan_log_sanitized_string (ctx->inbound.line);
|
||||
LOGERRORX ("'\n");
|
||||
err = ASSUAN_Connect_Failed;
|
||||
}
|
||||
}
|
||||
|
||||
if (err)
|
||||
{
|
||||
assuan_disconnect (ctx);
|
||||
}
|
||||
else
|
||||
*r_ctx = ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,169 +0,0 @@
|
||||
/* assuan-socket-server.c - Assuan socket based server
|
||||
* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of Assuan.
|
||||
*
|
||||
* Assuan is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Assuan 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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 <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "assuan-defs.h"
|
||||
|
||||
static int
|
||||
accept_connection_bottom (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
int fd = ctx->connected_fd;
|
||||
|
||||
ctx->client_pid = (pid_t)-1;
|
||||
#ifdef HAVE_SO_PEERCRED
|
||||
{
|
||||
struct ucred cr;
|
||||
int cl = sizeof cr;
|
||||
|
||||
if ( !getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl) )
|
||||
ctx->client_pid = cr.pid;
|
||||
}
|
||||
#endif
|
||||
|
||||
ctx->inbound.fd = fd;
|
||||
ctx->inbound.eof = 0;
|
||||
ctx->inbound.linelen = 0;
|
||||
ctx->inbound.attic.linelen = 0;
|
||||
ctx->inbound.attic.pending = 0;
|
||||
|
||||
ctx->outbound.fd = fd;
|
||||
ctx->outbound.data.linelen = 0;
|
||||
ctx->outbound.data.error = 0;
|
||||
|
||||
ctx->confidential = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
accept_connection (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr_un clnt_addr;
|
||||
size_t len = sizeof clnt_addr;
|
||||
|
||||
ctx->client_pid = (pid_t)-1;
|
||||
fd = accept (ctx->listen_fd, (struct sockaddr*)&clnt_addr, &len );
|
||||
if (fd == -1)
|
||||
{
|
||||
ctx->os_errno = errno;
|
||||
return ASSUAN_Accept_Failed;
|
||||
}
|
||||
|
||||
ctx->connected_fd = fd;
|
||||
return accept_connection_bottom (ctx);
|
||||
}
|
||||
|
||||
static int
|
||||
finish_connection (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
if (ctx->inbound.fd != -1)
|
||||
{
|
||||
close (ctx->inbound.fd);
|
||||
}
|
||||
ctx->inbound.fd = -1;
|
||||
ctx->outbound.fd = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
deinit_socket_server (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
finish_connection (ctx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Initialize a server for the socket LISTEN_FD which has already be
|
||||
put into listen mode */
|
||||
int
|
||||
assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd)
|
||||
{
|
||||
ASSUAN_CONTEXT ctx;
|
||||
int rc;
|
||||
|
||||
*r_ctx = NULL;
|
||||
ctx = xtrycalloc (1, sizeof *ctx);
|
||||
if (!ctx)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
ctx->is_server = 1;
|
||||
ctx->input_fd = -1;
|
||||
ctx->output_fd = -1;
|
||||
|
||||
ctx->inbound.fd = -1;
|
||||
ctx->outbound.fd = -1;
|
||||
|
||||
ctx->listen_fd = listen_fd;
|
||||
ctx->connected_fd = -1;
|
||||
ctx->deinit_handler = deinit_socket_server;
|
||||
ctx->accept_handler = accept_connection;
|
||||
ctx->finish_handler = finish_connection;
|
||||
|
||||
rc = _assuan_register_std_commands (ctx);
|
||||
if (rc)
|
||||
xfree (ctx);
|
||||
else
|
||||
*r_ctx = ctx;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Initialize a server using the already accepted socket FD. */
|
||||
int
|
||||
assuan_init_connected_socket_server (ASSUAN_CONTEXT *r_ctx, int fd)
|
||||
{
|
||||
ASSUAN_CONTEXT ctx;
|
||||
int rc;
|
||||
|
||||
*r_ctx = NULL;
|
||||
ctx = xtrycalloc (1, sizeof *ctx);
|
||||
if (!ctx)
|
||||
return ASSUAN_Out_Of_Core;
|
||||
ctx->is_server = 1;
|
||||
ctx->pipe_mode = 1; /* we wan't a second accept to indicate EOF */
|
||||
ctx->input_fd = -1;
|
||||
ctx->output_fd = -1;
|
||||
|
||||
ctx->inbound.fd = -1;
|
||||
ctx->outbound.fd = -1;
|
||||
|
||||
ctx->listen_fd = -1;
|
||||
ctx->connected_fd = fd;
|
||||
ctx->deinit_handler = deinit_socket_server;
|
||||
ctx->accept_handler = accept_connection_bottom;
|
||||
ctx->finish_handler = finish_connection;
|
||||
|
||||
rc = _assuan_register_std_commands (ctx);
|
||||
if (rc)
|
||||
xfree (ctx);
|
||||
else
|
||||
*r_ctx = ctx;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1,210 +0,0 @@
|
||||
/* assuan-util.c - Utility functions for Assuan
|
||||
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of Assuan.
|
||||
*
|
||||
* Assuan is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Assuan 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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 <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "assuan-defs.h"
|
||||
|
||||
#ifdef HAVE_JNLIB_LOGGING
|
||||
#include "../jnlib/logging.h"
|
||||
#endif
|
||||
|
||||
ssize_t (*_assuan_read_wrapper)(int,void*,size_t) = NULL;
|
||||
ssize_t (*_assuan_write_wrapper)(int,const void*,size_t) = NULL;
|
||||
|
||||
|
||||
static void *(*alloc_func)(size_t n) = malloc;
|
||||
static void *(*realloc_func)(void *p, size_t n) = realloc;
|
||||
static void (*free_func)(void*) = free;
|
||||
|
||||
|
||||
|
||||
void
|
||||
assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
|
||||
void *(*new_realloc_func)(void *p, size_t n),
|
||||
void (*new_free_func)(void*) )
|
||||
{
|
||||
alloc_func = new_alloc_func;
|
||||
realloc_func = new_realloc_func;
|
||||
free_func = new_free_func;
|
||||
}
|
||||
|
||||
void *
|
||||
_assuan_malloc (size_t n)
|
||||
{
|
||||
return alloc_func (n);
|
||||
}
|
||||
|
||||
void *
|
||||
_assuan_realloc (void *a, size_t n)
|
||||
{
|
||||
return realloc_func (a, n);
|
||||
}
|
||||
|
||||
void *
|
||||
_assuan_calloc (size_t n, size_t m)
|
||||
{
|
||||
void *p = _assuan_malloc (n*m);
|
||||
if (p)
|
||||
memset (p, 0, n* m);
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
_assuan_free (void *p)
|
||||
{
|
||||
if (p)
|
||||
free_func (p);
|
||||
}
|
||||
|
||||
/* For use with Pth it is required to have special read and write
|
||||
functions. We can't assume an ELF based system so we have to
|
||||
explicitly set them if we are going to use Pth. */
|
||||
void
|
||||
assuan_set_io_func (ssize_t (*r)(int,void*,size_t),
|
||||
ssize_t (*w)(int,const void*,size_t))
|
||||
{
|
||||
_assuan_read_wrapper = r;
|
||||
_assuan_write_wrapper = w;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Store the error in the context so that the error sending function
|
||||
can take out a descriptive text. Inside the assuan code, use the
|
||||
macro set_error instead of this function. */
|
||||
int
|
||||
assuan_set_error (ASSUAN_CONTEXT ctx, int err, const char *text)
|
||||
{
|
||||
ctx->err_no = err;
|
||||
ctx->err_str = text;
|
||||
return err;
|
||||
}
|
||||
|
||||
void
|
||||
assuan_set_pointer (ASSUAN_CONTEXT ctx, void *pointer)
|
||||
{
|
||||
if (ctx)
|
||||
ctx->user_pointer = pointer;
|
||||
}
|
||||
|
||||
void *
|
||||
assuan_get_pointer (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
return ctx? ctx->user_pointer : NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
assuan_set_log_stream (ASSUAN_CONTEXT ctx, FILE *fp)
|
||||
{
|
||||
if (ctx)
|
||||
{
|
||||
if (ctx->log_fp)
|
||||
fflush (ctx->log_fp);
|
||||
ctx->log_fp = fp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
assuan_begin_confidential (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
if (ctx)
|
||||
{
|
||||
ctx->confidential = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
assuan_end_confidential (ASSUAN_CONTEXT ctx)
|
||||
{
|
||||
if (ctx)
|
||||
{
|
||||
ctx->confidential = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length)
|
||||
{
|
||||
const unsigned char *s;
|
||||
int n;
|
||||
|
||||
for (n=length,s=buffer; n; n--, s++)
|
||||
{
|
||||
if (*s < ' ' || (*s >= 0x7f && *s <= 0xa0))
|
||||
break;
|
||||
}
|
||||
s = buffer;
|
||||
if (!n && *s != '[')
|
||||
fwrite (buffer, length, 1, fp);
|
||||
else
|
||||
{
|
||||
putc ('[', fp);
|
||||
for (n=0; n < length; n++, s++)
|
||||
fprintf (fp, " %02x", *s);
|
||||
putc (' ', fp);
|
||||
putc (']', fp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* print a user supplied string after filtering out potential bad
|
||||
characters*/
|
||||
void
|
||||
_assuan_log_sanitized_string (const char *string)
|
||||
{
|
||||
const unsigned char *s = string;
|
||||
#ifdef HAVE_JNLIB_LOGGING
|
||||
FILE *fp = log_get_stream ();
|
||||
#else
|
||||
FILE *fp = stderr;
|
||||
#endif
|
||||
|
||||
for (; *s; s++)
|
||||
{
|
||||
if (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))
|
||||
{
|
||||
putc ('\\', fp);
|
||||
if (*s == '\n')
|
||||
putc ('n', fp);
|
||||
else if (*s == '\r')
|
||||
putc ('r', fp);
|
||||
else if (*s == '\f')
|
||||
putc ('f', fp);
|
||||
else if (*s == '\v')
|
||||
putc ('v', fp);
|
||||
else if (*s == '\b')
|
||||
putc ('b', fp);
|
||||
else if (!*s)
|
||||
putc ('0', fp);
|
||||
else
|
||||
fprintf (fp, "x%02x", *s );
|
||||
}
|
||||
else
|
||||
putc (*s, fp);
|
||||
}
|
||||
}
|
||||
|
||||
|
234
assuan/assuan.h
234
assuan/assuan.h
@ -1,234 +0,0 @@
|
||||
/* assuan.c - Definitions for the Assuan protocol
|
||||
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of Assuan.
|
||||
*
|
||||
* Assuan is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* Assuan 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser 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 ASSUAN_H
|
||||
#define ASSUAN_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h> /* for ssize_t */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#if 0
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
ASSUAN_No_Error = 0,
|
||||
ASSUAN_General_Error = 1,
|
||||
ASSUAN_Out_Of_Core = 2,
|
||||
ASSUAN_Invalid_Value = 3,
|
||||
ASSUAN_Timeout = 4,
|
||||
ASSUAN_Read_Error = 5,
|
||||
ASSUAN_Write_Error = 6,
|
||||
ASSUAN_Problem_Starting_Server = 7,
|
||||
ASSUAN_Not_A_Server = 8,
|
||||
ASSUAN_Not_A_Client = 9,
|
||||
ASSUAN_Nested_Commands = 10,
|
||||
ASSUAN_Invalid_Response = 11,
|
||||
ASSUAN_No_Data_Callback = 12,
|
||||
ASSUAN_No_Inquire_Callback = 13,
|
||||
ASSUAN_Connect_Failed = 14,
|
||||
ASSUAN_Accept_Failed = 15,
|
||||
|
||||
/* error codes above 99 are meant as status codes */
|
||||
ASSUAN_Not_Implemented = 100,
|
||||
ASSUAN_Server_Fault = 101,
|
||||
ASSUAN_Invalid_Command = 102,
|
||||
ASSUAN_Unknown_Command = 103,
|
||||
ASSUAN_Syntax_Error = 104,
|
||||
ASSUAN_Parameter_Error = 105,
|
||||
ASSUAN_Parameter_Conflict = 106,
|
||||
ASSUAN_Line_Too_Long = 107,
|
||||
ASSUAN_Line_Not_Terminated = 108,
|
||||
ASSUAN_No_Input = 109,
|
||||
ASSUAN_No_Output = 110,
|
||||
ASSUAN_Canceled = 111,
|
||||
ASSUAN_Unsupported_Algorithm = 112,
|
||||
ASSUAN_Server_Resource_Problem = 113,
|
||||
ASSUAN_Server_IO_Error = 114,
|
||||
ASSUAN_Server_Bug = 115,
|
||||
ASSUAN_No_Data_Available = 116,
|
||||
ASSUAN_Invalid_Data = 117,
|
||||
ASSUAN_Unexpected_Command = 118,
|
||||
ASSUAN_Too_Much_Data = 119,
|
||||
ASSUAN_Inquire_Unknown = 120,
|
||||
ASSUAN_Inquire_Error = 121,
|
||||
ASSUAN_Invalid_Option = 122,
|
||||
ASSUAN_Invalid_Index = 123,
|
||||
ASSUAN_Unexpected_Status = 124,
|
||||
ASSUAN_Unexpected_Data = 125,
|
||||
ASSUAN_Invalid_Status = 126,
|
||||
|
||||
ASSUAN_Not_Confirmed = 128,
|
||||
|
||||
ASSUAN_Bad_Certificate = 201,
|
||||
ASSUAN_Bad_Certificate_Chain = 202,
|
||||
ASSUAN_Missing_Certificate = 203,
|
||||
ASSUAN_Bad_Signature = 204,
|
||||
ASSUAN_No_Agent = 205,
|
||||
ASSUAN_Agent_Error = 206,
|
||||
ASSUAN_No_Public_Key = 207,
|
||||
ASSUAN_No_Secret_Key = 208,
|
||||
ASSUAN_Invalid_Name = 209,
|
||||
|
||||
ASSUAN_Cert_Revoked = 301,
|
||||
ASSUAN_No_CRL_For_Cert = 302,
|
||||
ASSUAN_CRL_Too_Old = 303,
|
||||
ASSUAN_Not_Trusted = 304,
|
||||
|
||||
ASSUAN_Card_Error = 401,
|
||||
ASSUAN_Invalid_Card = 402,
|
||||
ASSUAN_No_PKCS15_App = 403,
|
||||
ASSUAN_Card_Not_Present = 404,
|
||||
ASSUAN_Invalid_Id = 405
|
||||
|
||||
} AssuanError;
|
||||
|
||||
/* This is a list of pre-registered ASSUAN commands */
|
||||
typedef enum {
|
||||
ASSUAN_CMD_NOP = 0,
|
||||
ASSUAN_CMD_CANCEL, /* cancel the current request */
|
||||
ASSUAN_CMD_BYE,
|
||||
ASSUAN_CMD_AUTH,
|
||||
ASSUAN_CMD_RESET,
|
||||
ASSUAN_CMD_OPTION,
|
||||
ASSUAN_CMD_DATA,
|
||||
ASSUAN_CMD_END,
|
||||
ASSUAN_CMD_INPUT,
|
||||
ASSUAN_CMD_OUTPUT,
|
||||
|
||||
ASSUAN_CMD_USER = 256 /* Other commands should be used with this offset*/
|
||||
} AssuanCommand;
|
||||
|
||||
#define ASSUAN_LINELENGTH 1002 /* 1000 + [CR,]LF */
|
||||
|
||||
struct assuan_context_s;
|
||||
typedef struct assuan_context_s *ASSUAN_CONTEXT;
|
||||
|
||||
/*-- assuan-handler.c --*/
|
||||
int assuan_register_command (ASSUAN_CONTEXT ctx,
|
||||
int cmd_id, const char *cmd_string,
|
||||
int (*handler)(ASSUAN_CONTEXT, char *));
|
||||
int assuan_register_bye_notify (ASSUAN_CONTEXT ctx,
|
||||
void (*fnc)(ASSUAN_CONTEXT));
|
||||
int assuan_register_reset_notify (ASSUAN_CONTEXT ctx,
|
||||
void (*fnc)(ASSUAN_CONTEXT));
|
||||
int assuan_register_cancel_notify (ASSUAN_CONTEXT ctx,
|
||||
void (*fnc)(ASSUAN_CONTEXT));
|
||||
int assuan_register_input_notify (ASSUAN_CONTEXT ctx,
|
||||
void (*fnc)(ASSUAN_CONTEXT, const char *));
|
||||
int assuan_register_output_notify (ASSUAN_CONTEXT ctx,
|
||||
void (*fnc)(ASSUAN_CONTEXT, const char *));
|
||||
|
||||
int assuan_register_option_handler (ASSUAN_CONTEXT ctx,
|
||||
int (*fnc)(ASSUAN_CONTEXT,
|
||||
const char*, const char*));
|
||||
|
||||
int assuan_process (ASSUAN_CONTEXT ctx);
|
||||
int assuan_process_next (ASSUAN_CONTEXT ctx);
|
||||
int assuan_get_active_fds (ASSUAN_CONTEXT ctx, int what,
|
||||
int *fdarray, int fdarraysize);
|
||||
|
||||
|
||||
FILE *assuan_get_data_fp (ASSUAN_CONTEXT ctx);
|
||||
AssuanError assuan_set_okay_line (ASSUAN_CONTEXT ctx, const char *line);
|
||||
void assuan_write_status (ASSUAN_CONTEXT ctx,
|
||||
const char *keyword, const char *text);
|
||||
|
||||
|
||||
/*-- assuan-listen.c --*/
|
||||
AssuanError assuan_set_hello_line (ASSUAN_CONTEXT ctx, const char *line);
|
||||
AssuanError assuan_accept (ASSUAN_CONTEXT ctx);
|
||||
int assuan_get_input_fd (ASSUAN_CONTEXT ctx);
|
||||
int assuan_get_output_fd (ASSUAN_CONTEXT ctx);
|
||||
AssuanError assuan_close_input_fd (ASSUAN_CONTEXT ctx);
|
||||
AssuanError assuan_close_output_fd (ASSUAN_CONTEXT ctx);
|
||||
|
||||
|
||||
/*-- assuan-pipe-server.c --*/
|
||||
int assuan_init_pipe_server (ASSUAN_CONTEXT *r_ctx, int filedes[2]);
|
||||
void assuan_deinit_server (ASSUAN_CONTEXT ctx);
|
||||
|
||||
/*-- assuan-socket-server.c --*/
|
||||
int assuan_init_socket_server (ASSUAN_CONTEXT *r_ctx, int listen_fd);
|
||||
int assuan_init_connected_socket_server (ASSUAN_CONTEXT *r_ctx, int fd);
|
||||
|
||||
|
||||
/*-- assuan-pipe-connect.c --*/
|
||||
AssuanError assuan_pipe_connect (ASSUAN_CONTEXT *ctx, const char *name,
|
||||
char *const argv[], int *fd_child_list);
|
||||
/*-- assuan-socket-connect.c --*/
|
||||
AssuanError assuan_socket_connect (ASSUAN_CONTEXT *ctx, const char *name,
|
||||
pid_t server_pid);
|
||||
|
||||
/*-- assuan-connect.c --*/
|
||||
void assuan_disconnect (ASSUAN_CONTEXT ctx);
|
||||
pid_t assuan_get_pid (ASSUAN_CONTEXT ctx);
|
||||
|
||||
/*-- assuan-client.c --*/
|
||||
AssuanError
|
||||
assuan_transact (ASSUAN_CONTEXT ctx,
|
||||
const char *command,
|
||||
AssuanError (*data_cb)(void *, const void *, size_t),
|
||||
void *data_cb_arg,
|
||||
AssuanError (*inquire_cb)(void*, const char *),
|
||||
void *inquire_cb_arg,
|
||||
AssuanError (*status_cb)(void*, const char *),
|
||||
void *status_cb_arg);
|
||||
|
||||
|
||||
/*-- assuan-inquire.c --*/
|
||||
AssuanError assuan_inquire (ASSUAN_CONTEXT ctx, const char *keyword,
|
||||
char **r_buffer, size_t *r_length, size_t maxlen);
|
||||
|
||||
/*-- assuan-buffer.c --*/
|
||||
AssuanError assuan_read_line (ASSUAN_CONTEXT ctx,
|
||||
char **line, size_t *linelen);
|
||||
int assuan_pending_line (ASSUAN_CONTEXT ctx);
|
||||
AssuanError assuan_write_line (ASSUAN_CONTEXT ctx, const char *line );
|
||||
AssuanError assuan_send_data (ASSUAN_CONTEXT ctx,
|
||||
const void *buffer, size_t length);
|
||||
|
||||
|
||||
/*-- assuan-util.c --*/
|
||||
void assuan_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
|
||||
void *(*new_realloc_func)(void *p, size_t n),
|
||||
void (*new_free_func)(void*) );
|
||||
void assuan_set_io_func (ssize_t (*r)(int,void*,size_t),
|
||||
ssize_t (*w)(int,const void*,size_t));
|
||||
void assuan_set_log_stream (ASSUAN_CONTEXT ctx, FILE *fp);
|
||||
int assuan_set_error (ASSUAN_CONTEXT ctx, int err, const char *text);
|
||||
void assuan_set_pointer (ASSUAN_CONTEXT ctx, void *pointer);
|
||||
void *assuan_get_pointer (ASSUAN_CONTEXT ctx);
|
||||
|
||||
void assuan_begin_confidential (ASSUAN_CONTEXT ctx);
|
||||
void assuan_end_confidential (ASSUAN_CONTEXT ctx);
|
||||
|
||||
/*-- assuan-errors.c (built) --*/
|
||||
const char *assuan_strerror (AssuanError err);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /*ASSUAN_H*/
|
@ -1,71 +0,0 @@
|
||||
#!/bin/sh
|
||||
# mkerrors - Extract error strings from assuan.h
|
||||
# and create C source for assuan_strerror
|
||||
# Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of Assuan.
|
||||
#
|
||||
# Assuan is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as
|
||||
# published by the Free Software Foundation; either version 2.1 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# Assuan 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
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser 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
|
||||
|
||||
cat <<EOF
|
||||
/* Generated automatically by mkerrors */
|
||||
/* Do not edit! */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "assuan.h"
|
||||
|
||||
/**
|
||||
* assuan_strerror:
|
||||
* @err: Error code
|
||||
*
|
||||
* This function returns a textual representaion of the given
|
||||
* errorcode. If this is an unknown value, a string with the value
|
||||
* is returned (Beware: it is hold in a static buffer).
|
||||
*
|
||||
* Return value: String with the error description.
|
||||
**/
|
||||
const char *
|
||||
assuan_strerror (AssuanError err)
|
||||
{
|
||||
const char *s;
|
||||
static char buf[25];
|
||||
|
||||
switch (err)
|
||||
{
|
||||
EOF
|
||||
|
||||
awk '
|
||||
/ASSUAN_No_Error/ { okay=1 }
|
||||
!okay {next}
|
||||
/}/ { exit 0 }
|
||||
/ASSUAN_[A-Za-z_]*/ { print_code($1) }
|
||||
|
||||
|
||||
function print_code( s )
|
||||
{
|
||||
printf " case %s: s=\"", s ;
|
||||
gsub(/_/, " ", s );
|
||||
printf "%s\"; break;\n", tolower(substr(s,8));
|
||||
}
|
||||
'
|
||||
|
||||
cat <<EOF
|
||||
default: sprintf (buf, "ec=%d", err ); s=buf; break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
EOF
|
171
checks/ChangeLog
171
checks/ChangeLog
@ -1,171 +0,0 @@
|
||||
2002-05-10 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* Makefile.am: Add gpg_dearmor to all targets where it is used.
|
||||
Noted by Andreas Haumer.
|
||||
|
||||
2002-04-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* signencrypt-dsa.test, sigs-dsa.test: Don't check with MD5 as
|
||||
this is not valid with DSA signatures.
|
||||
|
||||
2001-12-22 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* options.in: Add no-permission-warning.
|
||||
|
||||
2001-12-21 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* Makefile.am (distclean-local): prefix mkdemodirs with srcdir
|
||||
(DISTCLEANFILES): Add random_seed.
|
||||
|
||||
2001-12-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* options.in: Remove load-extension tiger
|
||||
* Makefile.am (./options): append it if there is such a module.
|
||||
|
||||
2001-10-23 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* defs.inc, Makefile.am: Do not use $srcdir when invoking gpg.
|
||||
Write the logfile to the current directory.
|
||||
|
||||
2001-09-28 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* defs.inc: Write a log file for each test.
|
||||
* run-gpg, run-gpgm, run-gpg.patterns: Removed. Replaced in all
|
||||
tests by a simple macro from defs.inc.
|
||||
* Makefile.am (CLEANFILES): Remove log files.
|
||||
(./gpg_dearmor): create it and use it instead of the macro.
|
||||
This is needed in multisig.test due to IFS tricks.
|
||||
|
||||
* armsignencrypt.test, signencrypt-dsa.test, signencrypt.test,
|
||||
armencryptp.test, armencrypt.test, encryptp.test, seat.test,
|
||||
encrypt-dsa.test, encrypt.test: Use --always-trust because the
|
||||
test are not designed to check the validity.
|
||||
|
||||
2001-09-06 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* genkey1024.test: Simplified by using a parameter file.
|
||||
|
||||
2001-05-30 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* multisig.test (IFS): Reset IFS just before the test.
|
||||
|
||||
2001-04-30 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* multisig.test: Add an set +x to avoid ksh problems
|
||||
|
||||
2001-04-28 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* run-gpg.patterns: a v3 test key expired yesterday, suppress the
|
||||
messages.
|
||||
|
||||
2001-03-27 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* defs.inc: Removed creation of options file.
|
||||
* options.in: New.
|
||||
* Makefile.am: Create options file and fixed import of pubdemo.asc.
|
||||
|
||||
* run-gpg.patterns (gpg): Add some more patterns.
|
||||
|
||||
2001-03-20 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* Makefile.am: Import the pubdemo.asc file
|
||||
|
||||
* sigs.test (hash_algo_list): s/tiger/tiger192/
|
||||
|
||||
2001-03-19 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* mkdemodirs (GPGDEMO): Add --allow-secret-key-import to all gpg
|
||||
invocations. Use echon -n instead of an argument with \c.
|
||||
|
||||
2001-02-12 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* multisig.test: new
|
||||
* Makefile.am (TESTS): Added.
|
||||
|
||||
2000-10-18 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* conventional-mdc.test: Add Rijndael and fix for empty plain texts.
|
||||
|
||||
Thu Feb 10 17:39:44 CET 2000 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* mkdemodirs: Fixed the --clean loop.
|
||||
|
||||
Thu Jan 13 19:31:58 CET 2000 Werner Koch <wk@gnupg.de>
|
||||
|
||||
* defs.inc (chdir): Removed becuase it is unsused an plain old sh
|
||||
does not like this name. Reported by Alec Habig.
|
||||
|
||||
Tue Oct 26 20:02:23 1999 Werner Koch (wk@gnupg.org)
|
||||
|
||||
* Makefile.am (GPG_DEARMOR): New and use --no-options.
|
||||
|
||||
Tue Aug 31 17:20:44 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* defs.inc: set LC_ALL empty
|
||||
|
||||
Wed Aug 4 10:34:18 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* defs.inc (echo_n): New and used instead of /bin/echo "\c"
|
||||
|
||||
Sun Apr 18 10:11:28 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* mkdemodirs: New
|
||||
* signdemokey: New.
|
||||
* Makefile.am (distclean-local): New.
|
||||
|
||||
Wed Mar 17 13:09:03 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* mds.test: replaced the "echo -n"
|
||||
|
||||
Mon Mar 8 20:47:17 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* pubdemo.asc, secdemo.asc: New.
|
||||
|
||||
Fri Feb 19 15:49:15 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* genkey1024.test: Be really quiet.
|
||||
|
||||
1999-01-01 Geoff Keating <geoffk@ozemail.com.au>
|
||||
|
||||
* Makefile.am (CLEANFILES): Also delete trustdb and any leftover
|
||||
lockfiles.
|
||||
|
||||
Fri Nov 27 15:30:24 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
|
||||
|
||||
* clearsig.test: Some more test cases.
|
||||
|
||||
Sun Oct 25 18:19:35 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* mds.test: Check whether TIGER is available.
|
||||
* sigs.tesr: Ditto.
|
||||
|
||||
Wed Sep 23 12:25:07 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* run-gpg.patterns: New (because Solaris fgrep does not like -f -).
|
||||
|
||||
Mon Aug 10 21:33:38 1998 Werner Koch (wk@(none))
|
||||
|
||||
* genkey1024.test: Ariel fixed this.
|
||||
|
||||
Wed Jul 8 10:43:47 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* seat.test: New.
|
||||
|
||||
Mon May 18 15:40:02 1998 Werner Koch (wk@isil.d.shuttle.de)
|
||||
|
||||
* Makefile.am: Now uses mk-tdata to produce random test data.
|
||||
|
||||
* ChangeLog: New.
|
||||
|
||||
|
||||
Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is free software; as a special exception the author gives
|
||||
unlimited permission to copy and/or distribute it, with or without
|
||||
modifications, as long as this notice is preserved.
|
||||
|
||||
This file is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
|
@ -1,107 +0,0 @@
|
||||
# Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GnuPG.
|
||||
#
|
||||
# GnuPG is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# GnuPG is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
|
||||
# Process this file with automake to create Makefile.in
|
||||
|
||||
GPG_IMPORT = ../g10/gpg --homedir . --quiet --yes --import
|
||||
|
||||
TESTS = version.test mds.test \
|
||||
decrypt.test decrypt-dsa.test \
|
||||
sigs.test sigs-dsa.test \
|
||||
encrypt.test encrypt-dsa.test \
|
||||
seat.test clearsig.test encryptp.test detach.test \
|
||||
armsigs.test armencrypt.test armencryptp.test \
|
||||
signencrypt.test signencrypt-dsa.test \
|
||||
armsignencrypt.test armdetach.test \
|
||||
armdetachm.test detachm.test genkey1024.test \
|
||||
conventional.test conventional-mdc.test \
|
||||
multisig.test
|
||||
|
||||
|
||||
TEST_FILES = pubring.asc secring.asc plain-1o.asc plain-2o.asc plain-3o.asc \
|
||||
plain-1.asc plain-2.asc plain-3.asc plain-1-pgp.asc \
|
||||
pubring.pkr.asc secring.skr.asc secdemo.asc pubdemo.asc options.in
|
||||
|
||||
DATA_FILES = data-500 data-9000 data-32000 data-80000 plain-large
|
||||
|
||||
EXTRA_DIST = defs.inc $(TESTS) $(TEST_FILES) \
|
||||
mkdemodirs signdemokey
|
||||
CLEANFILES = prepared.stamp x y yy z out err $(DATA_FILES) \
|
||||
plain-1 plain-2 plain-3 trustdb.gpg *.lock .\#lk* \
|
||||
*.test.log options gpg_dearmor \
|
||||
pubring.gpg secring.gpg pubring.pkr secring.skr
|
||||
DISTCLEANFILES = pubring.gpg~ random_seed
|
||||
|
||||
|
||||
all-local: prepared.stamp
|
||||
|
||||
distclean-local:
|
||||
$(srcdir)/mkdemodirs --clean
|
||||
|
||||
prepared.stamp: ./pubring.gpg ./secring.gpg ./plain-1 ./plain-2 ./plain-3 \
|
||||
./pubring.pkr ./secring.skr ./options ./gpg_dearmor \
|
||||
$(DATA_FILES)
|
||||
$(GPG_IMPORT) $(srcdir)/pubdemo.asc
|
||||
echo timestamp >./prepared.stamp
|
||||
|
||||
./options: $(srcdir)/options.in
|
||||
cat $(srcdir)/options.in >./options
|
||||
@set -e; if echo "@DYNAMIC_CIPHER_MODS@" |grep tiger >/dev/null ;then \
|
||||
echo load-extension ../cipher/tiger >>./options; fi
|
||||
|
||||
./gpg_dearmor:
|
||||
echo '#!/bin/sh' >./gpg_dearmor
|
||||
echo "../g10/gpg --no-options --no-greeting \
|
||||
--no-secmem-warning --batch --dearmor" >>./gpg_dearmor
|
||||
chmod 755 ./gpg_dearmor
|
||||
|
||||
./pubring.gpg: $(srcdir)/pubring.asc $(srcdir)/pubdemo.asc ./gpg_dearmor
|
||||
./gpg_dearmor > ./pubring.gpg < $(srcdir)/pubring.asc
|
||||
|
||||
./secring.gpg: $(srcdir)/secring.asc ./gpg_dearmor
|
||||
./gpg_dearmor > ./secring.gpg < $(srcdir)/secring.asc
|
||||
|
||||
./pubring.pkr: $(srcdir)/pubring.pkr.asc ./gpg_dearmor
|
||||
./gpg_dearmor > ./pubring.pkr < $(srcdir)/pubring.pkr.asc
|
||||
|
||||
./secring.skr: $(srcdir)/secring.skr.asc ./gpg_dearmor
|
||||
./gpg_dearmor > ./secring.skr < $(srcdir)/secring.skr.asc
|
||||
|
||||
./plain-1: $(srcdir)/plain-1o.asc ./gpg_dearmor
|
||||
./gpg_dearmor > ./plain-1 < $(srcdir)/plain-1o.asc
|
||||
|
||||
./plain-2: $(srcdir)/plain-2o.asc ./gpg_dearmor
|
||||
./gpg_dearmor > ./plain-2 < $(srcdir)/plain-2o.asc
|
||||
|
||||
./plain-3: $(srcdir)/plain-3o.asc ./gpg_dearmor
|
||||
./gpg_dearmor > ./plain-3 < $(srcdir)/plain-3o.asc
|
||||
|
||||
|
||||
data-500:
|
||||
../tools/mk-tdata 500 >data-500
|
||||
data-9000:
|
||||
../tools/mk-tdata 9000 >data-9000
|
||||
data-32000:
|
||||
../tools/mk-tdata 32000 >data-32000
|
||||
data-80000:
|
||||
../tools/mk-tdata 80000 >data-80000
|
||||
plain-large:
|
||||
cat $(srcdir)/../doc/HACKING \
|
||||
$(srcdir)/../doc/DETAILS \
|
||||
$(srcdir)/../doc/FAQ >plain-large
|
||||
|
@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
|
||||
#info Checking armored detached signatures
|
||||
for i in $plain_files $data_files ; do
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 -sab -o x --yes $i
|
||||
$GPG -o /dev/null --yes x <$i || error "$i: bad signature"
|
||||
done
|
||||
|
@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
#info Checking armored detached signatures of multiple files
|
||||
i="$plain_files $data_files"
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 -sab -o x --yes $i
|
||||
cat $i | $GPG -o /dev/null --yes x || error "$i: bad signature"
|
||||
|
@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
#info Checking armored encryption
|
||||
for i in $plain_files $data_files ; do
|
||||
$GPG --always-trust -ea -o x --yes -r "$usrname2" $i
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
@ -1,12 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
#info Checking armored encryption with a pipe
|
||||
for i in $plain_files $data_files ; do
|
||||
$GPG --always-trust -ea --yes -r "$usrname2" < $i | tee x | $GPG -o y --yes
|
||||
cmp $i y || error "$i: mismatch"
|
||||
$GPG --yes < x > y
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
@ -1,13 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
|
||||
#info Checking armored signing and encryption
|
||||
for i in $plain_files $data_files ; do
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --always-trust \
|
||||
-sae -o x --yes -r "$usrname2" $i
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
#info Checking armored signatures
|
||||
for i in $plain_files $data_files ; do
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 -sa -o x --yes $i
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
@ -1,42 +0,0 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: RIPEMD160
|
||||
|
||||
I promise to delivery 8 bottles of "Füchschen" to the first one who tells me
|
||||
the plaintext of the following message or is able to forge the signature
|
||||
on this file. Don't try to get my secret key, it does not exist any longer.
|
||||
For those who don't know: Füchschen is a beer brewed here in Düsseldorf.
|
||||
This promise is valid for 2 years from now (29.5.1998).
|
||||
|
||||
|
||||
Good luck,
|
||||
|
||||
Werner
|
||||
|
||||
|
||||
- -----BEGIN PGP MESSAGE-----
|
||||
Version: GNUPG v0.2.19 (GNU/Linux)
|
||||
Comment: This is an alpha version!
|
||||
|
||||
hQEOA+Pk8EXQYMj+FAP/V8XiybbbGVReNAKbknj9nqaHHVOjPdwBXyOBLRBEC5TiMhe/APmq
|
||||
XN3esJ/MU97eN9lZMVBLIwG4/jqzT/g2ULd3rZtWwgcyV1cDehGVun8cp0CbsM6QH8lhItLo
|
||||
fEqQ8u44q4ZO9drcswcA24Bn0j9dkX7sbyJTEtipj1LGjoUD/i5+e1sIQEWb5esA1WXIPWVS
|
||||
b8e8d/JnH4acQbTFH+1mrE2PtGD18IbM2PdTilcC/l4KNKcyWfsuoJmwoG5x/ciQUhpqn/fW
|
||||
WBjH99tbK8kIHSbgQ4FrMhS+I6Z3pH0EbViDC20f7TgZgGShVHUM/0BGcavVdd1vjUK4MZag
|
||||
kwJwpwBNGRPSazs8NKyjiAQupIC+xbZG+Qcz67xmOWU92qmfr3h6wrk8JJGsPOynGExJFNKv
|
||||
PwKckh3z7surZLhPeDMuZykGcEtFmJJbVBK+cIcAAA==
|
||||
=o6Ev
|
||||
- -----END PGP MESSAGE-----
|
||||
|
||||
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GNUPG v0.2.19 (GNU/Linux)
|
||||
Comment: This is an alpha version!
|
||||
|
||||
iQEXAwUBNW6hBuPk8EXQYMj+FAN5GQP+NhSpe3WmGfWYYQSOM4CxlgNv+EmpDvvDBCmxyKT6
|
||||
oVw+YD1b6q0XCkSx5u1b/ykwPbPS8VUxPqEKFBOtVWNQbCfmMRujUtPYWm8eomIHO3k7l0DF
|
||||
H8nah5gdwvOheB5YMUfhtuKQRk8/d8QRrsoc44OmB7znkLvQEMMaHxrgb5AD/31/TocHnNj6
|
||||
iC61cQrwTDSj2nLFWHn2yQ7uX5j9fBxCJgbQq6Aku17Z6LHDu6FfaMigS9l6s5VT2n4XuzFl
|
||||
qV2GMe20HU5JgrprU1cTULtr1yc3KUctnI3tcGt4UoF0Rt/IcPDdPTIcWScmUd01v4x1zVV9
|
||||
n6Qxh+yxRMwl+Oo+
|
||||
=gI9G
|
||||
-----END PGP SIGNATURE-----
|
@ -1,103 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
|
||||
# Fixme: we should not only do a --verify but also the output.
|
||||
|
||||
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
|
||||
# ======================================
|
||||
# I can't compare the out because plain-3 has no LF as last charcater
|
||||
# but the output has always one. I do not thinkl this is a bug, because
|
||||
# it is clear text and not binary text.
|
||||
# ======================================
|
||||
for i in $plain_files plain-large ; do
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 -sat -o x --yes $i
|
||||
$GPG --verify x
|
||||
done
|
||||
|
||||
# ======================================
|
||||
# and once more to check rfc1991
|
||||
# ======================================
|
||||
for i in $plain_files plain-large ; do
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 \
|
||||
--rfc1991 --digest-algo md5 -sat -o x --yes $i
|
||||
$GPG --verify x
|
||||
done
|
||||
|
||||
# ======================================
|
||||
# and one with long lines
|
||||
# ======================================
|
||||
cat >y <<EOF
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyx
|
||||
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
EOF
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --clearsign -o x --yes y
|
||||
$GPG --verify x
|
||||
|
||||
# ======================================
|
||||
# and one with only one long lines
|
||||
# ======================================
|
||||
cat >y <<EOF
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyx
|
||||
EOF
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --clearsign -o x --yes y
|
||||
$GPG --verify x
|
||||
# ======================================
|
||||
# and one with an empty body
|
||||
# ======================================
|
||||
cat >y <<EOF
|
||||
EOF
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --clearsign -o x --yes y
|
||||
$GPG --verify x
|
||||
|
||||
# ======================================
|
||||
# and one with one empty line at the end
|
||||
# ======================================
|
||||
cat >y <<EOF
|
||||
line 1
|
||||
line 2
|
||||
line 3
|
||||
there is a blank line after this
|
||||
|
||||
EOF
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --clearsign -o x --yes y
|
||||
$GPG --verify x
|
||||
|
||||
|
||||
# ======================================
|
||||
# I think this file will be constructed wrong (gpg 0.9.3)
|
||||
# but it should verify okay anyway.
|
||||
# ======================================
|
||||
echo "this is a sig test" >y
|
||||
echo_n " " >>y
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --clearsign -o x --yes y
|
||||
$GPG --verify x
|
||||
|
||||
|
||||
# ======================================
|
||||
# check our special diff mode
|
||||
# ======================================
|
||||
cat >y <<EOF
|
||||
--- mainproc.c Tue Jun 27 09:28:11 2000
|
||||
+++ mainproc.c~ Thu Jun 8 22:50:25 2000
|
||||
@@ -1190,16 +1190,13 @@
|
||||
md_enable( c->mfx.md, n1->pkt->pkt.signature->digest_algo);
|
||||
}
|
||||
/* ask for file and hash it */
|
||||
- if( c->sigs_only ) {
|
||||
+ if( c->sigs_only )
|
||||
rc = hash_datafiles( c->mfx.md, NULL,
|
||||
c->signed_data, c->sigfilename,
|
||||
n1? (n1->pkt->pkt.onepass_sig->sig_class == 0x01):0 );
|
||||
EOF
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 \
|
||||
--not-dash-escaped --clearsign -o x --yes y
|
||||
$GPG --verify x
|
||||
|
||||
|
||||
|
||||
|
@ -1,21 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
#info Checking conventional encryption
|
||||
for i in 0 1 2 3 9 10 11 19 20 21 22 23 39 40 41 8192 32000 ; do
|
||||
for ciph in 3des cast5 blowfish twofish rijndael; do
|
||||
# *BSD's dd can't cope with a count of 0
|
||||
if test "$i" = "0"; then
|
||||
: >z
|
||||
else
|
||||
dd if=data-80000 of=z bs=1 count=$i 2>/dev/null
|
||||
fi
|
||||
echo "Hier spricht HAL" | $GPG --passphrase-fd 0 \
|
||||
--force-mdc --cipher $ciph -c -o x --yes z
|
||||
echo "Hier spricht HAL" | $GPG --passphrase-fd 0 \
|
||||
-o y --yes x
|
||||
cmp z y || error "$ciph/$i: mismatch"
|
||||
done
|
||||
done
|
||||
|
@ -1,24 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
# temp. hack cause the format for 128 bit blocksize messages may change
|
||||
GNUPG_ENABLE_TWOFISH=1
|
||||
export GNUPG_ENABLE_TWOFISH
|
||||
|
||||
#info Checking conventional encryption
|
||||
for i in plain-2 data-32000 ; do
|
||||
echo "Hier spricht HAL" | $GPG --passphrase-fd 0 -c -o x --yes $i
|
||||
echo "Hier spricht HAL" | $GPG --passphrase-fd 0 -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
for a in cast5 3des twofish; do
|
||||
for i in plain-1 data-80000 ; do
|
||||
echo "Hier spricht HAL" | $GPG --passphrase-fd 0 \
|
||||
--cipher-algo $a -c -o x --yes $i
|
||||
echo "Hier spricht HAL" | $GPG --passphrase-fd 0 -o y --yes x
|
||||
cmp $i y || error "$i: ($a) mismatch"
|
||||
done
|
||||
done
|
||||
|
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
#info Checking decryption of supplied DSA encrypted file
|
||||
for i in "plain-1" ; do
|
||||
$GPG $dsa_keyrings -o y --yes $srcdir/$i-pgp.asc
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
#info Checking decryption of supplied files
|
||||
for i in $plain_files ; do
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 -o y --yes $srcdir/$i.asc
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
106
checks/defs.inc
106
checks/defs.inc
@ -1,106 +0,0 @@
|
||||
# definitions for the check scripts
|
||||
|
||||
#--------------------------------
|
||||
#------ constants ---------------
|
||||
#--------------------------------
|
||||
|
||||
# Note that usrpass1 is also used in Makefile.am
|
||||
usrname1="one"
|
||||
usrpass1="def"
|
||||
usrname2="two"
|
||||
usrpass2=""
|
||||
usrname3="three"
|
||||
usrpass3="abc"
|
||||
|
||||
|
||||
dsa_usrname1="pgp5"
|
||||
# we use the sub key because we do not yet have the logic to
|
||||
# to derive the first encryption key from a keyblock (I guess)
|
||||
dsa_usrname2="0xCB879DE9"
|
||||
|
||||
dsa_keyrings="--keyring ./pubring.pkr --secret-keyring ./secring.skr"
|
||||
|
||||
|
||||
plain_files="plain-1 plain-2 plain-3"
|
||||
data_files="data-500 data-9000 data-32000 data-80000"
|
||||
exp_files=""
|
||||
|
||||
# The testscripts expect the original language
|
||||
LANG=
|
||||
LANGUAGE=
|
||||
LC_ALL=
|
||||
LC_MESSAGES=
|
||||
|
||||
#--------------------------------
|
||||
#------ utility functions -------
|
||||
#--------------------------------
|
||||
|
||||
fatal () {
|
||||
echo "$pgmname: fatal:" $* >&2
|
||||
exit 1;
|
||||
}
|
||||
|
||||
error () {
|
||||
echo "$pgmname:" $* >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
info () {
|
||||
echo "$pgmname:" $* >&2
|
||||
}
|
||||
|
||||
|
||||
echo_n_init=no
|
||||
echo_n () {
|
||||
if test "$echo_n_init" = "no"; then
|
||||
if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
|
||||
if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
|
||||
echo_n_n=
|
||||
echo_n_c='
|
||||
'
|
||||
else
|
||||
echo_n_n='-n'
|
||||
echo_n_c=
|
||||
fi
|
||||
else
|
||||
echo_n_n=
|
||||
echo_n_c='\c'
|
||||
fi
|
||||
echo_n_init=yes
|
||||
fi
|
||||
echo $echo_n_n "${1}$echo_n_c"
|
||||
}
|
||||
|
||||
|
||||
#cleanup () {
|
||||
# rm $cleanup_files 2>/dev/null || true
|
||||
# echo "#empty" >./options
|
||||
#}
|
||||
|
||||
|
||||
#add_cleanup () {
|
||||
# cleanup_files="$cleanup_files $*"
|
||||
#}
|
||||
|
||||
|
||||
have_hash_algo () {
|
||||
if ../g10/gpg --homedir . --version | grep "Hash:.*$1" >/dev/null
|
||||
then
|
||||
true
|
||||
else
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
set -e
|
||||
pgmname=`basename $0`
|
||||
#trap cleanup SIGHUP SIGINT SIGQUIT
|
||||
|
||||
[ -z "$srcdir" ] && fatal "not called from make"
|
||||
|
||||
GPG="../g10/gpg --homedir . "
|
||||
|
||||
exec 2> ${pgmname}.log
|
||||
|
||||
:
|
||||
# end
|
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
#info Checking detached signatures
|
||||
for i in $plain_files $data_files ; do
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 -sb -o x --yes $i
|
||||
$GPG -o /dev/null --yes x <$i || error "$i: bad signature"
|
||||
done
|
||||
|
@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
#info Checking detached signatures of multiple files
|
||||
i="$plain_files $data_files"
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 -sb -o x --yes $i
|
||||
cat $i | $GPG -o /dev/null --yes x || error "$i: bad signature"
|
||||
|
@ -1,19 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
#info Checking encryption
|
||||
for i in $plain_files $data_files ; do
|
||||
$GPG $dsa_keyrings --always-trust -e -o x --yes -r "$dsa_usrname2" $i
|
||||
$GPG $dsa_keyrings -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
# and with cast
|
||||
for i in $plain_files $data_files ; do
|
||||
$GPG $dsa_keyrings --always-trust --cipher-algo cast5 -e \
|
||||
-o x --yes -r "$dsa_usrname2" $i
|
||||
$GPG $dsa_keyrings -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
@ -1,16 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
#info Checking encryption
|
||||
for i in $plain_files $data_files ; do
|
||||
$GPG --always-trust -e -o x --yes -r "$usrname2" $i
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
for i in $plain_files $data_files ; do
|
||||
$GPG --always-trust -e -o x --yes -r "$usrname2" --cipher-algo cast5 $i
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
#info Checking encryption with a pipe
|
||||
for i in $plain_files $data_files ; do
|
||||
$GPG --always-trust -e --yes -r "$usrname2" <$i | $GPG --yes > y
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
@ -1,26 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
../g10/gpg --quiet --batch --quick-random --homedir . --gen-key <<EOF
|
||||
Key-Type: DSA
|
||||
Key-Length: 1024
|
||||
Subkey-Type: ELG-E
|
||||
Subkey-Length: 1024
|
||||
Name-Real: Harry H.
|
||||
Name-Comment: test key
|
||||
Name-Email: hh@@ddorf.de
|
||||
Expire-Date: 1
|
||||
Passphrase: abc
|
||||
%commit
|
||||
Key-Type: RSA
|
||||
Key-Length: 1024
|
||||
Key-Usage: sign,encrypt
|
||||
Name-Real: Harry A.
|
||||
Name-Comment: RSA test key
|
||||
Name-Email: hh@@ddorf.de
|
||||
Expire-Date: 2
|
||||
Passphrase: abc
|
||||
%commit
|
||||
EOF
|
||||
|
@ -1,40 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
|
||||
test_one () {
|
||||
if [ "`grep $1 y | sed -e 's/.*=[ ]\(.*\)/\1/' -e 's/ //g'`" != "$2" ]; then
|
||||
failed="$failed $1"
|
||||
fi
|
||||
}
|
||||
|
||||
failed=""
|
||||
|
||||
#info Checking message digests
|
||||
cat /dev/null | $GPG -v --print-mds >y
|
||||
test_one "MD5" "D41D8CD98F00B204E9800998ECF8427E"
|
||||
test_one "SHA1" "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709"
|
||||
test_one "RMD160" "9C1185A5C5E9FC54612808977EE8F548B2258D31"
|
||||
if have_hash_algo "TIGER"; then
|
||||
test_one "TIGER" "24F0130C63AC933216166E76B1BB925FF373DE2D49584E7A"
|
||||
else
|
||||
echo "Hash algorithm TIGER/192 is not installed"
|
||||
fi
|
||||
|
||||
[ "$failed" != "" ] && error "$failed failed for empty string"
|
||||
|
||||
echo_n "abcdefghijklmnopqrstuvwxyz" | $GPG --print-mds >y
|
||||
test_one "MD5" "C3FCD3D76192E4007DFB496CCA67E13B"
|
||||
test_one "SHA1" "32D10C7B8CF96570CA04CE37F2A19D84240D3A89"
|
||||
test_one "RMD160" "F71C27109C692C1B56BBDCEB5B9D2865B3708DBC"
|
||||
if have_hash_algo "TIGER"; then
|
||||
test_one "TIGER" "307DE5EE72A414172A0355CCBF120404E9EE7BF32F60110B"
|
||||
fi
|
||||
|
||||
|
||||
[ "$failed" != "" ] && error "$failed failed for a..z"
|
||||
|
||||
exit 0
|
||||
|
@ -1,37 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
GPG="../g10/gpg --batch --quiet --no-secmem-warning --allow-secret-key-import"
|
||||
NAMES='Alpha Bravo Charlie Delta Echo Foxtrot Golf Hotel India
|
||||
Juliet Kilo Lima Mike November Oscar Papa Quebec Romeo
|
||||
Sierra Tango Uniform Victor Whisky XRay Yankee Zulu'
|
||||
|
||||
if [ "$1" = "--clean" ]; then
|
||||
(for i in $NAMES; do
|
||||
[ -d $i ] && rm -r $i
|
||||
done) || true
|
||||
exit 0
|
||||
fi
|
||||
|
||||
$GPG --dearmor -o secdemo.gpg --yes ../checks/secdemo.asc
|
||||
$GPG --dearmor -o pubdemo.gpg --yes ../checks/pubdemo.asc
|
||||
[ -f ./tdb.tmp ] && rm ./tdb.tmp
|
||||
GPGDEMO="$GPG --homedir . --trustdb-name ./tdb.tmp --no-default-keyring
|
||||
--keyring pubdemo.gpg --secret-keyring secdemo.gpg"
|
||||
echo -n "Creating:"
|
||||
for name in $NAMES; do
|
||||
echo -n " $name"
|
||||
[ -d $name ] && rm -r $name
|
||||
mkdir $name
|
||||
$GPGDEMO --export-secret-key -o - $name > $name/Secret.gpg
|
||||
$GPG --homedir $name --import $name/Secret.gpg
|
||||
$GPGDEMO --export -o - $name > $name/Public.gpg
|
||||
$GPG --homedir $name --import $name/Public.gpg
|
||||
[ -f $name/pubring.gpg~ ] && rm $name/pubring.gpg~
|
||||
done
|
||||
echo "."
|
||||
[ -f ./tdb.tmp ] && rm ./tdb.tmp
|
||||
rm pubdemo.gpg secdemo.gpg
|
||||
|
||||
|
@ -1,145 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Check that gpg verifies only signatures where there is no ambiguity
|
||||
# in the order of packets. Needs the Demo Keys Lima and Mike.
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
# (variable intialization was created using:
|
||||
# for i in files; do echo "`echo $i | sed 's,[.-],_,g'`='"; \
|
||||
# gpg --no-version --enarmor <$i | grep -v ^Comment:; echo "'" ; done
|
||||
# )
|
||||
|
||||
sig_1ls1ls_valid='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
kA0DAAIRN8q1H7eRA/gBrCdiBXRleHQxOogq9EkgYW0gc29ycnksIEkgY2FuJ3Qg
|
||||
ZG8gdGhhdAqIPwMFADqIKvQ3yrUft5ED+BEC2joAoJaSaXOZEtSZqQ780HIXG77e
|
||||
8PB7AJ4wCprmaFTO0fBaTcXDuEOBdAWnOZANAwACETfKtR+3kQP4AawnYgV0ZXh0
|
||||
MTqIKvRJIGFtIHNvcnJ5LCBJIGNhbid0IGRvIHRoYXQKiD8DBQA6iCr0N8q1H7eR
|
||||
A/gRAto6AKCWkmlzmRLUmakO/NByFxu+3vDwewCeMAqa5mhUztHwWk3Fw7hDgXQF
|
||||
pzk=
|
||||
=8jSC
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_ls_valid='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
rCdiBXRleHQxOogrS0kgYW0gc29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqI
|
||||
K0s3yrUft5ED+BECLQMAn2jZUNOpB4OuurSQkc2TRfg6ek02AJ9+oJS0frQ+yUsT
|
||||
QDUFTH2PvZRxjw==
|
||||
=J+lb
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_sl_valid='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
iD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeDrrq0kJHNk0X4OnpNNgCffqCU
|
||||
tH60PslLE0A1BUx9j72UcY+sJ2IFdGV4dDE6iCtLSSBhbSBzb3JyeSwgSSBjYW4n
|
||||
dCBkbyB0aGF0Cg==
|
||||
=N9MP
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_11lss_valid_but_is_not='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
kA0DAAIRN8q1H7eRA/gAkA0DAAIRN8q1H7eRA/gBrCdiBXRleHQxOogyXUkgYW0g
|
||||
c29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqIMl03yrUft5ED+BECwQAAnRXT
|
||||
mXjVd385oD38W80XuheWKTGcAJ9pZ6/flaKDfw+SLido7xaUHuhp5Yg/AwUAOogy
|
||||
XTfKtR+3kQP4EQLBAACgnN0IP+NztE0aAc/DZ17yHWR9diwAniN0P01WmbgZJoZB
|
||||
Q341WRXKS/at
|
||||
=Ekrs
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_11lss11lss_valid_but_is_not='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
kA0DAAIRN8q1H7eRA/gAkA0DAAIRN8q1H7eRA/gBrCdiBXRleHQxOogyXUkgYW0g
|
||||
c29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqIMl03yrUft5ED+BECwQAAnRXT
|
||||
mXjVd385oD38W80XuheWKTGcAJ9pZ6/flaKDfw+SLido7xaUHuhp5Yg/AwUAOogy
|
||||
XTfKtR+3kQP4EQLBAACgnN0IP+NztE0aAc/DZ17yHWR9diwAniN0P01WmbgZJoZB
|
||||
Q341WRXKS/atkA0DAAIRN8q1H7eRA/gAkA0DAAIRN8q1H7eRA/gBrCdiBXRleHQx
|
||||
OogyXUkgYW0gc29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqIMl03yrUft5ED
|
||||
+BECwQAAnRXTmXjVd385oD38W80XuheWKTGcAJ9pZ6/flaKDfw+SLido7xaUHuhp
|
||||
5Yg/AwUAOogyXTfKtR+3kQP4EQLBAACgnN0IP+NztE0aAc/DZ17yHWR9diwAniN0
|
||||
P01WmbgZJoZBQ341WRXKS/at
|
||||
=P1Mu
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_ssl_valid_but_is_not='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
iD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeDrrq0kJHNk0X4OnpNNgCffqCU
|
||||
tH60PslLE0A1BUx9j72UcY+IPwMFADqIK0s3yrUft5ED+BECLQMAn2jZUNOpB4Ou
|
||||
urSQkc2TRfg6ek02AJ9+oJS0frQ+yUsTQDUFTH2PvZRxj6wnYgV0ZXh0MTqIK0tJ
|
||||
IGFtIHNvcnJ5LCBJIGNhbid0IGRvIHRoYXQK
|
||||
=Zven
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_1lsls_invalid='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
kA0DAAIRN8q1H7eRA/gBrCdiBXRleHQxOogq9EkgYW0gc29ycnksIEkgY2FuJ3Qg
|
||||
ZG8gdGhhdAqIPwMFADqIKvQ3yrUft5ED+BEC2joAoJaSaXOZEtSZqQ780HIXG77e
|
||||
8PB7AJ4wCprmaFTO0fBaTcXDuEOBdAWnOawnYgV0ZXh0MTqIK0tJIGFtIHNvcnJ5
|
||||
LCBJIGNhbid0IGRvIHRoYXQKiD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeD
|
||||
rrq0kJHNk0X4OnpNNgCffqCUtH60PslLE0A1BUx9j72UcY8=
|
||||
=nkeu
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_lsls_invalid='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
rCdiBXRleHQxOogrS0kgYW0gc29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqI
|
||||
K0s3yrUft5ED+BECLQMAn2jZUNOpB4OuurSQkc2TRfg6ek02AJ9+oJS0frQ+yUsT
|
||||
QDUFTH2PvZRxj6wnYgV0ZXh0MTqIK0tJIGFtIHNvcnJ5LCBJIGNhbid0IGRvIHRo
|
||||
YXQKiD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeDrrq0kJHNk0X4OnpNNgCf
|
||||
fqCUtH60PslLE0A1BUx9j72UcY8=
|
||||
=BlZH
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_lss_invalid='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
rCdiBXRleHQxOogrS0kgYW0gc29ycnksIEkgY2FuJ3QgZG8gdGhhdAqIPwMFADqI
|
||||
K0s3yrUft5ED+BECLQMAn2jZUNOpB4OuurSQkc2TRfg6ek02AJ9+oJS0frQ+yUsT
|
||||
QDUFTH2PvZRxj4g/AwUAOogrSzfKtR+3kQP4EQItAwCfaNlQ06kHg666tJCRzZNF
|
||||
+Dp6TTYAn36glLR+tD7JSxNANQVMfY+9lHGP
|
||||
=jmt6
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
sig_slsl_invalid='
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
|
||||
iD8DBQA6iCtLN8q1H7eRA/gRAi0DAJ9o2VDTqQeDrrq0kJHNk0X4OnpNNgCffqCU
|
||||
tH60PslLE0A1BUx9j72UcY+sJ2IFdGV4dDE6iCtLSSBhbSBzb3JyeSwgSSBjYW4n
|
||||
dCBkbyB0aGF0Cog/AwUAOogrSzfKtR+3kQP4EQItAwCfaNlQ06kHg666tJCRzZNF
|
||||
+Dp6TTYAn36glLR+tD7JSxNANQVMfY+9lHGPrCdiBXRleHQxOogrS0kgYW0gc29y
|
||||
cnksIEkgY2FuJ3QgZG8gdGhhdAo=
|
||||
=phBF
|
||||
-----END PGP ARMORED FILE-----
|
||||
'
|
||||
|
||||
save_IFS="${IFS}"
|
||||
IFS=""
|
||||
for i in "$sig_1ls1ls_valid" "$sig_ls_valid" "$sig_sl_valid"; do
|
||||
echo "$i" | ./gpg_dearmor >x
|
||||
IFS="${save_IFS}"
|
||||
$GPG --verify x 2>/dev/null || error "valid is invalid"
|
||||
IFS=""
|
||||
done
|
||||
#for i in "$sig_11lss_valid_but_is_not" "$sig_11lss11lss_valid_but_is_not" \
|
||||
# "$sig_ssl_valid_but_is_not"; do
|
||||
# echo "$i" | $GPG --dearmor >x
|
||||
# $GPG --verify <x 2>/dev/null || error "valid is invalid"
|
||||
#done
|
||||
|
||||
# without the +e ksh seems to terminate the for loop
|
||||
set +e
|
||||
for i in "$sig_1lsls_invalid" "$sig_lsls_invalid" \
|
||||
"$sig_lss_invalid" "$sig_slsl_invalid" ; do
|
||||
echo "$i" | ./gpg_dearmor >x
|
||||
IFS="${save_IFS}"
|
||||
$GPG --verify <x 2>/dev/null && error "invalid is valid"
|
||||
IFS=""
|
||||
done
|
||||
IFS="${save_IFS}"
|
@ -1,6 +0,0 @@
|
||||
no-greeting
|
||||
no-secmem-warning
|
||||
no-permission-warning
|
||||
batch
|
||||
emulate-md-encode-bug
|
||||
no-auto-check-trustdb
|
@ -1,14 +0,0 @@
|
||||
Type Bits/KeyID Date User ID
|
||||
pub 888/A50283F1 2001/11/08 pgp2.6.3-test-key
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: 2.6.3a
|
||||
|
||||
mQB8AzvqRosAAAEDeNMKLJMJQeGC2RG5Nec6R2mzC12N1wGLiYYJCsmSQd1Y8mht
|
||||
A2Sc+4k/q5+l6GHtfqUR/RTCIIudAZUzrQVIMhHDKF+5de9lsE5QxQS1u43QGVCb
|
||||
/9IYrOLOizYQ2pkBtD9LCrf7W2DccMEkpQKD8QAFE7QRcGdwMi42LjMtdGVzdC1r
|
||||
ZXmJAIQDBRA76kaL3HDBJKUCg/EBAZMoA3Yqqdix6B2RAzywi9bKSLqwAFVL+MMw
|
||||
W+BnYeBXF9u+bPpQvtyxgi0vx8F9r84B3HAhZNEjBWODF6vctIQhXhAhXIniDTSj
|
||||
HNzQ/+nbWnebQn18XUV2SdM1PzMOblD+nISte7+WUfWzlD7YUJPkFPw=
|
||||
=b498
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
@ -1,18 +0,0 @@
|
||||
Type Bits/KeyID Date User ID
|
||||
sec 888/A50283F1 2001/11/08 pgp2.6.3-test-key
|
||||
|
||||
-----BEGIN PGP SECRET KEY BLOCK-----
|
||||
Version: 2.6.3a
|
||||
|
||||
lQGdAzvqRosAAAEDeNMKLJMJQeGC2RG5Nec6R2mzC12N1wGLiYYJCsmSQd1Y8mht
|
||||
A2Sc+4k/q5+l6GHtfqUR/RTCIIudAZUzrQVIMhHDKF+5de9lsE5QxQS1u43QGVCb
|
||||
/9IYrOLOizYQ2pkBtD9LCrf7W2DccMEkpQKD8QAFEwADd0Kk5aeyFM3zbPgfikkE
|
||||
7iFg9h2LG3nARmA4wAnCZaQ3CS5zRHCdXOf5KLkm6xFza1yMat4iWx6ULvuuNpIc
|
||||
RmkHccyXYkRi3Hvacd5A9VCNw1UKtCdaCKgacsfplU0s1xYWGZd4J8Jg8boSfW5W
|
||||
gwG8Dc9R20HHno8uD2vfr5rg8ElWvbFyJI/j4eCVAd+NYAGNvB8I3VP38IIYcavh
|
||||
YYcGjrpxbGVRybsBvA9IJltpGaVulxwpeCp5NecCGgoAUsN4Ktf42Pg7HXDlQL6r
|
||||
Xs/YggMztj4NzEgBHXAOLShdKKhDAbEByVSKXZD9A8J+RejXBl6VbuJmD/5qOvph
|
||||
GAPKS3ahPDj8438HyD7yIDLYYVRKfxjWHLubc46Pgui0EXBncDIuNi4zLXRlc3Qt
|
||||
a2V5
|
||||
=l/aV
|
||||
-----END PGP SECRET KEY BLOCK-----
|
@ -1,29 +0,0 @@
|
||||
This is an encrypted version of plain-1 for
|
||||
the PGP test key 0xCB879DE9 using CAST.
|
||||
|
||||
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
Version: PGPfreeware 5.0i for non-commercial use
|
||||
MessageID: D0P6k4cfvaTDkyRQM+/MpOoQW6xT5Swm
|
||||
|
||||
qANQR1DBwA4DW3oC8MuHnekQAwDj3tkgY6XU+e1k9XOlSSzIPGenxgOZ8VSvuEUd
|
||||
L+/1E9T2KJmH5CGyH4Hz6wIOLtFSd1A13yYRyHNhxD/nGgcjg6etZNVQnjPuRp5k
|
||||
O4jYz2BCstkjz793ZjPzgXgdpt0C/0zmlQz8clT+/cswAj0t1famcz/Ai4gexfkI
|
||||
pojmFHewdYs6FT0XbwxjaYUyw955KBEUwJ4uJ6VTR5ab4GxUmpHn/S7HfoWVPjXl
|
||||
j7R8Xw/5bsrOCjA5hd2XcpE95lTHzcnB9Fr57OMFlFC/FSwUaDsArZ/V8sUJnD+l
|
||||
aWyrDhzuiwVy2XSYiX55qCL3zuZsiElo6AS7ITkI8onL2FIFtC3L5LecPprNlE68
|
||||
XJLxNZUSAel7OcnwqUNtM1lEK6bfYfiXr0BBEkg1Jfx/KucHMIara0CVEh+V0aGj
|
||||
I8rKt3MS+T7KMYgJzf47ipTtf0Q3qZph28fRirn8gKBlEIRz62WU9Jjz/GrNqbuD
|
||||
meixSq3JprnK2kDZ00oqSZVCjFEc6pQoZqZc0cGT6IDpYEsNghfeyCxzUB17QzJC
|
||||
gisd5k0uSCIWO8lwbWInnDzmV8XTfG5o4u88S89ioGydxMlCcNNX2cNp/MH/chgk
|
||||
iSI+BAZ6mVcKdH2x6NpFJDGcogIM9phsnUC8NkOUH2FtjnCxDJyKSfML4lrEIi3x
|
||||
QCAFEx+dYq4xcT8AnEQcTJ4ppoUJwfbtqXxYh2TKSWSkXnNz6sp2AGlx/uc99CyB
|
||||
BjurpFQzseceTbxfJySm3LMJ470jSmwXSl3byryfiwTVV7BYoKkYfpVaXK4VHVMS
|
||||
bw15DEH8PqjkxRabokwhIpWsJ4ta+FCgaDYhdOvrBAztwm9edsYYiNdrwjn8zFzw
|
||||
QpOqh7h0uCksU5/ULmadIAYgejPyGJM6lv2m7o0xay4TOqyRMzkdcu0WyR3PVFAE
|
||||
iwk/uYIonNCJc3pFS8k4b3CYnSiso0z1ugJR5YcPoOuxrbdly1om4ZC0is+euQZN
|
||||
kzSGwfbabKY3mvRWGTGpZil43BRMK7nzL6oN0f7Y+/DTRp4Vzc0NTyfV2QkU25Il
|
||||
ARs4Cxa138Nw4fmfvenCvv2QL2Ks/HCM7lybhq2IvbRVRiOEgcPxvRtZ5VKrqbkM
|
||||
rrzzqi2PxlVrinR2GAkNu75ef+FP/KWP4NFYvEMpDxqXNS7Ju1sfcyFaTnm9
|
||||
=TpZW
|
||||
-----END PGP MESSAGE-----
|
@ -1,32 +0,0 @@
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
Version: GNUPG v0.2.15a (Linux)
|
||||
Comment: This is an alpha version!
|
||||
|
||||
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
|
||||
=a0yS
|
||||
-----END PGP MESSAGE-----
|
@ -1,28 +0,0 @@
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
Version: GNUPG v0.3.4 (GNU/Linux)
|
||||
Comment: Get GNUPG from ftp://ftp.guug.de/pub/gcrypt/
|
||||
Comment: Use "gpgm --dearmor" for unpacking
|
||||
|
||||
PCEtLSBEaWVzIGlzdCBTZWl0ZSAzLCBkb3J0IGlzdCBrZWluZSBTZWl0ZW56YWhsIGFuZ2Vn
|
||||
ZWJlbiwKICAgICBvYmVuIHJlY2h0cyBpc3Qgd2llZGVyIGRlciBTdGVtcGVsIHZvbiBtZWlu
|
||||
ZW0gT3BhIHp1IGZpbmRlbiAtLT4KCjxzZWN0MT5OYW1lIDxxPkdyb98tQmFydGxvZmY8Lz4K
|
||||
CjxwPgpEZXIgTmFtZSA8cS9CYXJ0bG9mZi8gaXN0IHNjaHdlciB6dSBkZXV0ZW4uIE1hbiBo
|
||||
YXQgdmllbGUgTXV0bWHfdW5nZW4KYW5nZXN0ZWxsdCwgdm9uIGRlbmVuIG1hbiBhYmVyIGJp
|
||||
c2xhbmcga2VpbmUgZWluemlnZSBhbHMgdW5iZWRpbmd0CnJpY2h0aWcgZXJrbORyZW4ga2Fu
|
||||
bi4KPGZvbnRpbmZvIHJlbT0ibWl0IExlZXJ6ZWljaGVuIGdlc2NocmllYmVuIj5Vcmt1bmRs
|
||||
aWNoPC8+IHdpcmQgZGFzCkRvcmYgYmlzIHp1ciBSZWZvcm1hdGlvbiBzdGV0cyA8cS9CYXJ0
|
||||
b3JmLyAoYW5ubyAxMjUzKSB1bmQKPHEvQmFyZG9yZi8gKDEzMDYsIDEzMTgsIDEzMjksIDE0
|
||||
MjkpIGdlbmFubnQgdW5kIGRhc18gc293b2hsIEtsZWluLQp3aWUgR3Jv32JhcnRsb2ZmLiBF
|
||||
cnN0IDE1ODYgaW0gQmlzY2hvZnNzdGVpbmVyIEp1cmlzZGlrdGlvbmFsYnVjaApoZWnfdCB1
|
||||
bnNlciBEb3JmIDxxL0JhcnR0ZWxvZmYvIHVuZCBzbyBhdWNoIGluIGRlciDkbHRlc3RlbiBu
|
||||
b2NoCnZvcmhhbmRlbmVuIEtpcmNoZW5yZWNobnVuZyB2b20gSmFocmUgMTY1MS4gTkFjaCBk
|
||||
ZW0gSmFocmUgMTcwMCB3aXJkCmluIGRlbiBVcmt1bmRlbiBiZWdvbm5lbiwgZGVuIHZvbGxl
|
||||
biBOYW1lbiA8cS9Hcm/fLUJhcnRsb2ZmLyB1bmQKPHEvS2xlaW4tQmFydGxvZmYvIHp1IHNj
|
||||
aHJlaWJlbi4KLS0tLS0tLS0tLS0tLS0tLSBbd2VnZW4gZGFzaGVkIGVzY2FwZWQgdGV4dF0K
|
||||
PHA+Ck5pbW10IG1hbiBhbiwgZGHfIGRpZSB1cmt1bmRsaWNoZSwg5Gx0ZXN0ZSBCZXplaWNo
|
||||
bnVuZyBCYXJ0b3JmIGRpZQp1cnNwcvxuZ2xpY2hlIGlzdCB1bmQgbmljaHQgZGllIG11bmRh
|
||||
cnRsaWNoZSBCYXJ0bG9mZiwgc28ga/ZubnRlIGRlcgpOYW1lIGd1dCBnZWRldXRldCB3ZXJk
|
||||
ZW4gYWxzIERvcmYgYW4gZGVyIDxxL0JvcmRlLyBvZGVyIGFtIFJhbmRlCm9kZXIgYW4gZGVy
|
||||
IEdyZW56ZSBlbnR3ZWRlciBkZXMgV2FsZGVzCg==
|
||||
=m1k/
|
||||
-----END PGP ARMORED FILE-----
|
@ -1,41 +0,0 @@
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
Version: GNUPG v0.2.15a (Linux)
|
||||
Comment: This is an alpha version!
|
||||
|
||||
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
|
||||
suFI5P95Yw==
|
||||
=08za
|
||||
-----END PGP MESSAGE-----
|
@ -1,36 +0,0 @@
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
Version: GNUPG v0.3.4 (GNU/Linux)
|
||||
Comment: Get GNUPG from ftp://ftp.guug.de/pub/gcrypt/
|
||||
Comment: Use "gpgm --dearmor" for unpacking
|
||||
|
||||
Cgo8c2VjdD5Wb3J3b3J0CjxwPgpEZXIgV2VydCBlaW5lciBPcnRzY2hyb25payBpc3Qgb2Zm
|
||||
ZW5iYXIgdW5kIGJlZGFyZiBrZWluZXIgRXL2cnRlcnVuZy4KTWl0IEF1c2JydWNoIGRlcyBX
|
||||
ZWx0a3JpZWdlc18sIGlubWl0dGVuIGRlciBnZXdhbHRpZ2VuIEdlc2NoZWhuaXNzZSwgZvxo
|
||||
bHRlCmRlciBLbGVydXNfIHVuc2VyZXNfIEVpY2hzX2ZlbGRlc18gZGFzXyBtZWhyIHdpZSBm
|
||||
cvxoZXIgdW5kIHNvCmVyc3Rhcmt0ZSBkYXNfIFN0cmViZW4sIGVpbmUgc29sY2hlIE9ydHNf
|
||||
Z2VzY2hpY2h0ZSB6dSBzY2FoZmZlbiwgdW0KdW5zZXJlbiBOYWNoa29tbWVuIHp1IGJlcmlj
|
||||
aHRlbiwgd2FzXyBhdWNoIGRpZSBrbGVpbnN0ZW4gRPZyZmVyIGluCmRlciBncm/fZW4gWmVp
|
||||
dCBnZWxlaXN0ZXQsIGVybGVidCB1bmQgZXJsaXR0ZW4gaGFiZW4uCjxwPgpVbmQgc28gYmVn
|
||||
YW5uIGF1Y2ggaWNoIGltIERlemVtYmVyIDE5MTQsIGRlbiA/Pz8/Pz8/Pz8KU3RvZmYsIHdv
|
||||
IGltbWVyIGljaCBpaG4gYXVjaCBudXIgc28gc3DkcmxpY2ggZmluZGVuIGtvbm50ZSwgenUK
|
||||
c2FtbWVsbiwgaWNoIGJlZnJhZ3RlIHp1buRjaHN0IGVtc2lnIGRpZSDkbHRlc3RlbiBMZXV0
|
||||
ZSwKZHVyY2hmb3JzY2h0ZSBzb2Rhbm4gZGFzIGdhbnplIFBmYXJyYXJjaGl2LCBkYXMgU2No
|
||||
dWx6ZW5hcmNoaXYKYmVpZGVyIFBmYXJyZPZyZmVyLCBkYXMgS29tbWlzc2FyaWF0c19hcmNo
|
||||
aXYgenUgSGVpbGlnZW5zdGFkdCwKZW5kbGljaCBhdWNoIDE5MTYgZGFzIFN0YWF0c19hcmNo
|
||||
aXYgenUgTWFnZGVidXJnLiBTZWxic3R2ZXJzdORuZGxpY2gKYXJiZWl0ZXRlIGljaCBhdWNo
|
||||
IGRpZSBlaW5zY2hs5GdpZ2UgTGl0ZXJhdHVyIGR1cmNoLiBHYXIgdmllbGUgWmVpdAp1bmQg
|
||||
TfxoZSBoYXQgZXNfIGdla29zdGV0IHVtIG5hY2ggbWVociBhbHMgOCBKYWhyZW4gZGllIE9y
|
||||
dHNjaHJvbmlrIHZvbgpHcm/fYmFydGxvZmYgdW5kIHZvbSBGaWxpYWxkb3JmIFdpbGJpY2gg
|
||||
Z2Vzb25kZXJ0IHp1IHNjaGFmZmVuLgo8cCB2c3BhY2U9IjJleCI+CjxiZj5Hcm/fYmFydGxv
|
||||
ZmYsPC8+IGRlbiAyMy4gTeRyeiAxOTIzLgo8cCB2c3BhY2U9IjNleCIgYWxpZ249cmlnaHQ+
|
||||
CjxiZi9OaWtvbGF1cyBH9nJpbmcsLyBQZmFycmVyLgo8L3A+Cgo8IS0tIEhpZXIgZm9sZ3Qg
|
||||
ZWluIFN0ZW1wZWwgdm9uIG1laW5lbSBPcGE6CgkgIFJ1ZC4gS29jaAogICAgIEdyb99iYXJ0
|
||||
bG9mZi9FaWNoc2ZlbGQKCUFuZ2VyIDE2MQotLT4KPCEtLSBGSVhNRTogaGllciBrb21tdCBl
|
||||
aW5lbiBaaWVybGluaWUgLS0+Cgo8cCB2c3BhY2U9ZmlsbD4gPCEtLSBEZXIgUmVzdCBrYW0g
|
||||
YW0gRW5kZSBkZXIgU2VpdGUgLS0+CjxwIGFsaWduPWNlbnRlcj4gTGl0ZXJhdHVyOiA8L3A+
|
||||
CjEpIEpvaC4gV29sZjogUG9saXRpc2NoZSBHZXNjaGljaHRlIGRlcyBFaWNoc2YuIEf2dHQu
|
||||
IDE3OTIgdW5kCkz2ZmZsZXIgMTkyMS4gMikgSy4gR2VzY2hpY2h0ZSwgV29sZiAxODE2IEf2
|
||||
dHQuICAzKSBLbmllYjogR2VzY2guCmRlciBSZWYuIHUuIEdlZ2VucmVmPz8/Cgo8IS0tIEZJ
|
||||
WE1FOiBEZXIgUmVzdCBmZWhsdCBub2NoIC0tPgoKCgoKCgoKCjwvc2VjdD4K
|
||||
=9nnj
|
||||
-----END PGP ARMORED FILE-----
|
@ -1,13 +0,0 @@
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
Version: GNUPG v0.2.15a (Linux)
|
||||
Comment: This is an alpha version!
|
||||
|
||||
0CIjY3JlYXRlZCBieSBHTlVQRyB2MC4yLjE1YSAoTGludXgpowJ4nAEYAef+hM4DPGu75p0m
|
||||
bg8QAwDAGvCZWrqo7Rt8DNg7tDI8ckhL1XfN0OZuy/tJjD8o1K1JuXPfCpAX2WI69PvlVhPC
|
||||
RO9F2WaBTqyo/fY5XVSzNlfin9TMe56gFjhT3vhK0IgZ1gjBuowY4TktVq4cG/YC/0hX3u6L
|
||||
7M9D0H0ye0YgRof82sRHKQBSeuFn5iHc6hSB7fFXsyDLqmEvclDV0exY1a3giTGwUX81fknR
|
||||
EwzB2weemUnf1DQ8rGhw/dBiarOMjjWz0ypyfhWqV/U3RNZRIaRGjBtl0Qbr51KIvg3UnaGD
|
||||
YX8DXWpV61kkRX+DsQ27tuQvW6V8lKcsElipIFXPhCpfdSnGGVjx69gGDSFEhMLcSy3s4i4X
|
||||
MMVwiy8=
|
||||
=MnS6
|
||||
-----END PGP MESSAGE-----
|
@ -1,10 +0,0 @@
|
||||
Stored by G10, because diff/patch have problems with
|
||||
files not having a trailing LF - and this one has none.
|
||||
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
Version: G10 v0.2.6a (Linux)
|
||||
Comment: This is an alpha version!
|
||||
|
||||
RGllcyBpc3QgZWluZSBlaW5mYWNoZSBaZWlsZSBvaG5lIExGIGFtIEVuZGUu
|
||||
=ZQ6m
|
||||
-----END PGP ARMORED FILE-----
|
@ -1,566 +0,0 @@
|
||||
26 demo keys:
|
||||
|
||||
pub 1024D/68697734 1999-03-08 Alpha Test (demo key) <alpha@example.net>
|
||||
uid Alice (demo key)
|
||||
uid Alfa Test (demo key) <alfa@example.net>
|
||||
sub 1024g/46A871F8 1999-03-08
|
||||
pub 1024D/1AFDAB6C 1999-03-08 Charlie Test (demo key) <charlie@example.net>
|
||||
sub 1024g/BC43DA60 1999-03-08
|
||||
pub 1024D/FAEF6D1B 1999-03-08 Echo Test (demo key) <echo@example.net>
|
||||
uid Eve (demo key)
|
||||
uid Echelon (demo key)
|
||||
sub 1024g/7272144D 1999-03-08
|
||||
pub 1024D/8FC282E6 1999-03-08 Golf Test (demo key) <golf@example.net>
|
||||
sub 1024g/9DCAD354 1999-03-08
|
||||
pub 1024D/04259677 1999-03-08 India Test (demo key) <india@example.net>
|
||||
sub 1024g/61F76C73 1999-03-08
|
||||
pub 1024D/43C2D0C7 1999-03-08 Kilo Test (demo key) <kilo@example.net>
|
||||
sub 1024g/9AF64D02 1999-03-08
|
||||
pub 1024D/A9E3B0B2 1999-03-08 Bravo Test (demo key) <bravo@example.net>
|
||||
uid Bob (demo key)
|
||||
sub 1024g/E29BA37F 1999-03-08
|
||||
pub 1024D/EB9DC9E6 1999-03-08 Delta Test (demo key) <delta@example.net>
|
||||
sub 1024g/B0C45424 1999-03-08
|
||||
pub 1024D/7372E243 1999-03-08 Foxtrot Test (demo key) <foxtrot@example.net>
|
||||
sub 1024g/EE45198E 1999-03-08
|
||||
pub 1024D/34C6E3F1 1999-03-08 Hotel Test (demo key) <hotel@example.net>
|
||||
sub 1024g/D622AD0A 1999-03-08
|
||||
pub 1024D/D2699313 1999-03-08 Juliet Test (demo key) <juliet@example.net>
|
||||
sub 1024g/35F8F136 1999-03-08
|
||||
pub 1024D/B79103F8 1999-03-08 Lima Test (demo key) <lima@example.net>
|
||||
sub 1024g/FE56350C 1999-03-08
|
||||
pub 1024D/BE5CF886 1999-03-08 Mike Test (demo key) <mike@example.net>
|
||||
uid Mallory (demo key)
|
||||
sub 1024g/4F31EAE8 1999-03-08
|
||||
pub 1024D/30CEC684 1999-03-08 November Test (demo key) <november@example.net>
|
||||
sub 1024g/8B70E472 1999-03-08
|
||||
pub 1024D/6D9732AC 1999-03-08 Oscar Test (demo key) <oscar@example.net>
|
||||
sub 1024g/2681619F 1999-03-08
|
||||
pub 1024D/3FF13206 1999-03-08 Papa test (demo key) <papa@example.net>
|
||||
sub 1024g/63330D9C 1999-03-08
|
||||
pub 1024D/3C661C84 1999-03-08 Quebec Test (demo key) <quebec@example.net>
|
||||
sub 1024g/A029ACF4 1999-03-08
|
||||
pub 1024D/777FBED3 1999-03-08 Romeo Test (demo key) <romeo@example.net>
|
||||
sub 1024g/11D102EA 1999-03-08
|
||||
pub 1024D/A3AE3EA1 1999-03-08 Sierra Test (demo key) <sierra@example.net>
|
||||
sub 1024g/0F1B50B4 1999-03-08
|
||||
pub 1024D/85A81F38 1999-03-08 Tango Test (demo key) <tango@example.net>
|
||||
sub 1024g/101C0402 1999-03-08
|
||||
pub 1024D/653244D6 1999-03-08 Uniform Test (demo key) <uniform@example.net>
|
||||
sub 1024g/5522BDB9 1999-03-08
|
||||
pub 1024D/61F04784 1999-03-08 Victor Test (demo key) <victor@example.org>
|
||||
sub 1024g/07287134 1999-03-08
|
||||
pub 1024D/EC67DBDE 1999-03-08 Whisky Test (demo key) <whisky@example.net>
|
||||
sub 1024g/FD6E27F6 1999-03-08
|
||||
pub 1024D/567FB34A 1999-03-08 XRay Test (demo key) <xray@example.net>
|
||||
sub 1024g/41E408BE 1999-03-08
|
||||
pub 1024D/4B11B25F 1999-03-08 Yankee Test (demo key) <yankee@example.net>
|
||||
sub 1024g/F7B080AD 1999-03-08
|
||||
pub 1024D/54ACD246 1999-03-08 Zulu Test (demo key) <zulu@example.net>
|
||||
sub 1024g/A172C881 1999-03-08
|
||||
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: GnuPG v0.9.3 (GNU/Linux)
|
||||
Comment: For info see http://www.gnupg.org
|
||||
|
||||
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
|
||||
=1N8S
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
@ -1,734 +0,0 @@
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
Version: GnuPG v1.0.7 (GNU/Linux)
|
||||
Comment: Use "gpg --dearmor" for unpacking
|
||||
|
||||
mM8DNUWBuARHEAMA8bSQw1VFSXbgZ+nNXhM9xeDD+OpKQU4hUaCKfuTtRHoY5QxT
|
||||
Pz3DFWRlFewsA50Ou28jlPWxIKZaaGxMqbDtqyUsm6AEz/vRi5VKiVHf28XUkMry
|
||||
QSTHvjwJFVb7+6WbAAMFAwDXZiawNtgYsjwVedv/xXdhTsrf0Tn/8HCj3S9N/MAT
|
||||
0zCnXL0flYeqhqL/okuBcrwMA4amAIWGVW7ws7k7QgrfJoWG2SELxIT9MovMLvq5
|
||||
Kh55J7H6Yn6uoFzIOX0A43HQIiNjcmVhdGVkIGJ5IEdOVVBHIHYwLjIuMTVhIChM
|
||||
aW51eCm0KFRlc3Qgb25lIChwcD1kZWYpIDxvbmVAdGVzdC5ub3doZXJlLm5pbD6I
|
||||
1wMFEzVFgbg8a7vmnSZuDxADD/4DAK0FELG1gICh/fxO5dXulV+S1CY9YPQwRxQN
|
||||
7zYlixA7vedTCN9jutMC6fOlmMXqfivF2CMux3uz0oTJgjF/myh+jkcOsE+iUgcO
|
||||
+fdMIn4oY53Pval5zuCcmqqbszP6mQMAqIYYNtE2BI6acRU8sqwIxx/GiVqELwzX
|
||||
4QGp5N/4oURoZJ4Ybb8+6eEePI1vzIpLq9TO0ttQzDv9hO8WNyYEPVAoe9gOIoMY
|
||||
Oh9E0W9Ru0wf4sh67KCrRvc7yrFTMwHtiN8DBRA1RYLMDvng6C5fpPQQAzlHAx4q
|
||||
EZmAhoAtCfgQmlmqHIwcOa2xI/eOsqexT6eYMty8f/vsNznGhTh5gJ3PDDy8U/Lj
|
||||
1KRJWPeDSZJ/6tZ/3DUd/x+KjPzVVnm1zlJSflR5AWLS7IQiyJzz7uo2dUiCs2nO
|
||||
4rZcAyDaLbj/2aWwI92UQzKjWvcS49lWr2wp0QURUomqvNexKkHHDyIRhwspXwT9
|
||||
glETyn+focZKRBJTv0QtxOMVQeGaUnIuAcsDgpZuZkXBcdXgPbmj39rN+nNUW1UI
|
||||
0fKsnBl5cnSgiNcDBRA1RYLaZE80um0R1tMQAwq4Av9rzmMgXgDtJy+mauJJ5FUE
|
||||
E5GY3bIul1MuIbaMv6T99uWgwD9q2HsV0z9/T552cOTJ/DIkSjdusZ6+PlY8jYDK
|
||||
4xTYwcglPuMH5/EsKW8zZwcwYiqnGMbmY4F70SxZW2EC/1p760rM7MrNCDAWnEle
|
||||
gTvEMvutfK+K3DOu+Ba+KxU3zfgWr4z6B74QV2TvHrF0Zgu9UpXOp0FghufA6Jev
|
||||
CvYhzNDM4VJV24QaF3bt16JoHQyiS9jtYcMl4IzexeeO0JjXAzVFggEAABADINyO
|
||||
1leIKxvoee6oi0zkI9SCJ6dSTEH7/kETqetNArjqClenO1K0AVd+MqMajl97bg5i
|
||||
UYGam55PECkkozOlscDzDF9exWY6sey44dBREQhgXLVWE4GZ1G3sy85aD+sVHgxw
|
||||
lz8AAwUDILAV8w6FL7PpgiedAOHslMtqf7sh1IeNSkCjRdqvMCKgKroSLQto9Wpr
|
||||
XMUv3KHmTL7TpZNad+8xJUK7R5GHUTR1OIFQMJvTodG8RU6JOaGoeTqWgs61v00f
|
||||
FgwY6sYO11ckmsfQIiNjcmVhdGVkIGJ5IEdOVVBHIHYwLjIuMTVhIChMaW51eCm0
|
||||
J3Rlc3QgdHdvIChubyBwcCkgPHR3b0B0ZXN0Lm5vd2hlcmUubmlsPojfAwUTNUWC
|
||||
AQ754OguX6T0EAOQsQMfXrBhe1g+hBCwQH94+08VqNGS/+Fs8s4FRmEP1Y0TuT6U
|
||||
qf9QLHtfbPgKbJL1NwGgy6dn4TfWo2PRj0U8ai+YIIPZopl4hnrj+v1f94V/IbMd
|
||||
3N77K0F0rJrHzL4egHi95BUVdgMgr00QAYcbbZItd/wIb2TNSu/DRlzEXezA3xRu
|
||||
CIBnTdsrHMPc2B4lmCQsyx9/fmBlwrVLlaftBTvrOUa/yXf8hHwPv48avRwgClao
|
||||
ChExhFMdEA9Df5ju4192VldJyJgPVz0Ze4jXAwUQNUWCsTxru+adJm4PEAOeIwMA
|
||||
hzYyjVb5vlae3V3VO+5+Zsx4SVRB2NeCY74FIN5vXMoWJyt/UjmXC9CmI82PvVD3
|
||||
F8RXKUZqZC9gXcGyDYyZ87oooYc9HbQ7lhyOWsv/0dWztX9UQQrHdScQ0TbZcC2a
|
||||
AvwJF7WESAGhOGssVKWaUkXZJV1sCpyyEtkUP/UJtcGha/OpPlmG6vC9XW5ymtRk
|
||||
0XhFkvG4dLopbRIZgAI0CmHSloKIL5Y4JzOfc5bccNCB/tiI+3Y1JIr3AYMqaSTj
|
||||
oGOI1gMFEDVFgwJkTzS6bRHW0xAD83sC93MCuEN8MCJGTZX//I7QVsg5DJ9xJRdy
|
||||
5Te6MNA1Ie1o7+EJZ1MqDVF/6+HkITqGWFOPD/GYPmgdP5QALfHW6z9YddHOHH6S
|
||||
kt2fC2NWTip4e+/t8iAOR/ynwocPpyHkAwCHsxTXtRlaCbIt40/3d0LFPoN4JYBV
|
||||
DM+pWfNgNAWUzgMEMua2P24g4P4NZnW3fsJuYQ6Ro7jqu6oolfFkxVOYd2/KrnH5
|
||||
Mggu3D8q+gg68kzXTj62QW9vTBax5Ve0Kk+YzwM1RYJlAAAQAwCWZQsoNJJI8u1n
|
||||
V+5VZaXZqZBn+uk3fp/my7l9YLQeV5S9U76Ogdw0la/YiWX2m8Aw+hO47pYswsyR
|
||||
i2lu/FE/dr0o0CB53LB4EnFJPiBHrB8rm3wI142BQeJ9Dj5YU/MAAwYC/1gB0NoF
|
||||
l2QhbYY83tuLg/UlIkM8CZtxtXR9vfQq0UgrVuDoeLx0/mlnWm8pmJsHR+0r8sL2
|
||||
yjl7P0RQ+FJtiaMTVHihJyhXukCO1bPM3PX8L/QsmXFzWcfmavk11xpPNdAiI2Ny
|
||||
ZWF0ZWQgYnkgR05VUEcgdjAuMi4xNWEgKExpbnV4KbQsdGVzdCB0aHJlZSAocHA9
|
||||
YWJjKSA8dGhyZWVAdGVzdC5ub3doZXJlLm5pbD6I1wMFEzVFgmVkTzS6bRHW0xAD
|
||||
VtEDAIWyFsZZgyT9wLmEsVbLcv2WNK/z7XweyDOV203Z3Po5lo75+c8bFkRPNcD/
|
||||
0R/nD5wbyNPACFHxe7VUm+wLHZFq5Hw8TuAegqNq0ZlgeR/vLgs54m1eOi3jbDfy
|
||||
ZMJASAL/XKRGnGu3oi6SjknKsKhFOprdn7DeMW0q7YP5WtRTnnrJjIhDl0c+mi82
|
||||
Yj2OVEOLg3SaILBDZJd9muLPHQLAp95XsKZ0nHfBzlFFsr0V5BvWF4UV+U9JHxyD
|
||||
uXLWyEDbiNcDBRA1RYK7PGu75p0mbg8QA3mwAvsHXEo6HotEGw0stskTnV/Dp32b
|
||||
SJ8yRq2kOWfQAgaY1ZZWVRSPtHBDAJZJ/LpfWXPke90M3B72v0a9gAxOx5Vfevaa
|
||||
XJAdp/ZjrVh1TE90LujbPVNeHt4a1dD0bQa9EbwC/1NTZMfb8LDHxYdsJdDdZxsx
|
||||
fCDy2U7BWC1e3LLQCJOeNfSx76ICJBLq+HOpCgP2AodGgV9Rx01O3Fz8Gx3iVRgZ
|
||||
bKnyS8perkS3AFayedGat/6reUI6KJtddro0SIeBxIjfAwUQNUWDEw754OguX6T0
|
||||
EAPKMgMeL8YKAj4KvkJBWNxt1W+WTjF2YBj4pYmrWisXxgmRZWEwwyDHYecH1zE2
|
||||
L12o82QGprbU8BW+GUXQVxbRt0rvlDqfGPN5HAgdjES7sK3qVZLsVeMcnhpjDDQk
|
||||
pYkCIsWueCKKRwMfSiqZ1S3oBHIz3CVzbQkdMp6FbpSYXRR55CyzVdUZDb9ynXKx
|
||||
QCk3Pmn0bTFsRWRFOlRe3oVpS2lM2EQFu5cWheypAt2y86ZuoevHPkcpsR0UXD12
|
||||
9IzwOV3cstGm3jCAhdGMmJkBogQ2446eEQQAtmWxQ19MJiSPMiw2EHSImXgLhy5n
|
||||
8h7Kl2ixlDGbVogL5/4TaXLcGoZsypuaF4px1L1JCzkNLPKzpbteZ4cOGs3N9K0z
|
||||
9S7CJJ+czkTZxXYGAukSsoTnopv+t/v8hrXZ05uPZVX2gqsLBJgQhJF2nlgxqvon
|
||||
tW/PSfPU+p/yarsAoKEJI1XlRhvgf0syevson3R1kFZHA/0Vw8i11+Plhxj9mnre
|
||||
dV5SqI1hsLGZnPSzz2IcFP0XFDu3HtUEG9FxZVFRQYWNCUKTP7cv5DYvmhlhc4oG
|
||||
0PhwFmZFLwPPlSAFZ3jfqfkh4RiMi01yqQGE6uOgML5ZWeQqb39Ngqf/ltWlcgNK
|
||||
pwVjMniMV5kfRzoupccZ+XI2owP/VWbnzl1qgl5Ab8+Dst0ORW40ENP/rcvKw5/D
|
||||
k2oj4uNRclJxIuizvqsgUtPRY52Y/vj5HEXF1vfUjcZhCUWOzLjR7ecCLxB9ozRD
|
||||
ifZbM82RQQ27sLI1xyt+fpT2xhMuvcQj9uohGn8rCim0VyYRNQvrZPEpyvhputrI
|
||||
r5iv+Wq0KUFscGhhIFRlc3QgKGRlbW8ga2V5KSA8YWxwaGFAZXhhbXBsZS5uZXQ+
|
||||
iF0EExECABUFAjbjjp4DCwoDAxUDAgMWAgECF4AAEgkQLXJ8x2hpdzQHZUdQRwAB
|
||||
ATl4AKCBLmRplv/8ZfSqep5IjqEAuaXvWwCgl6NEzT+/WewPTGcwZY+pLkycLv20
|
||||
EEFsaWNlIChkZW1vIGtleSmIXQQTEQIAFQUCNuO2qwMLCgMDFQMCAxYCAQIXgAAS
|
||||
CRAtcnzHaGl3NAdlR1BHAAEBJ4wAn0x5RWtqCjklzo93B143k4zBvLftAKCFbrlx
|
||||
lNCUPVsGUir9AzxvP0A3gbQnQWxmYSBUZXN0IChkZW1vIGtleSkgPGFsZmFAZXhh
|
||||
bXBsZS5uZXQ+iF0EExECABUFAjbjuFgDCwoDAxUDAgMWAgECF4AAEgkQLXJ8x2hp
|
||||
dzQHZUdQRwABAbfCAKCT8Guo/lZuVYtzb7qPCWa4uDyfwwCfXam5miXQfBXSZx3x
|
||||
oda1yt8vyXK5AQ0ENuOPDxAEAJyN1x9X9LsjfX2Z8O9s7BzMO9OoOxFtvZw+FA0B
|
||||
uDs0WVYkq1GuZ9/XiO0K30zvtZnlb7NMvBfz7xbLeYx+vKzy5xkq18+LE5dU+HKK
|
||||
dRQZKrrwgCsDy8tJRO447QsiLTksCDqPMaE32OCRBF5nKrG5vih7/cmEhf2CuAn+
|
||||
2yM3AAMHA/0Z5eYysaLnAwPeqQ9vNvUyrCxUEmrvl4svG7zkkg3ZcgAbDpDQUmni
|
||||
jt3gEBCoAzO3c41TU5wJaUNBEPGPWfKcTlmBEGJWjK50QQuA2diGncxIS5SDs+QV
|
||||
af434a6/KFVQcCmV7K8/T2S8/nuGJ/rIlFL5XovW6A/S9mYEjh2pD4hOBBgRAgAG
|
||||
BQI2448PABIJEC1yfMdoaXc0B2VHUEcAAQEgqQCfcDXmD8uNVdKg/C9vqI3JSndq
|
||||
knsAnRxzVeHi/iJ73OCKtvFrHbV9GogqmQGiBDbjkGcRBAC/DCQungO2iJ7j9+9q
|
||||
d2crjBU8K+AmQhs27JBkJqtAbC/xFqkHBsA1Pi8Zb6TLa/OCm2PbXFiM5x00wiEn
|
||||
VKNzuGOzU8uHB6kwWtLj8+V7VOWOkSDEtnlTF6u0y9JOvs7GwDvqOM5C3QH7La+z
|
||||
nNeAu1527Hj6l0XGSAzyvp+NkwCgnktU11VFpKSIdoplZBayN9OzT8sD/Awc/890
|
||||
fiSMWYNGo4+n6IHxhjBBM9lL+DAe1RtCEtwUSWNrGsIxFnDRkMxvMpaT4GusG+DP
|
||||
haTddrDBSyFiCLxKDBYgMbSO6wQ9g6zWEEh1ZMTMVU/akr81DOEColXn/f3Q4sRj
|
||||
xI3hu2z8tjVewAPNTuWETQ6iHHoVqdpkK4aABACfbMrnfK6TujxSs91MfKBWfYxy
|
||||
w9hjM6+VV8cJJdDXiheMKzWcrVecwgYYzukmNinO//BRmQcs1wdfi5UdfHLNFDig
|
||||
w96SdyZpHx+79ghD3NqDmzYakoRIoDKcZAIrAjgfl5if6vIiA4c1LjhSdcVTBsSy
|
||||
ic/mkk01EgztWKY0abQtQ2hhcmxpZSBUZXN0IChkZW1vIGtleSkgPGNoYXJsaWVA
|
||||
ZXhhbXBsZS5uZXQ+iF0EExECABUFAjbjkGcDCwoDAxUDAgMWAgECF4AAEgkQQT9K
|
||||
8xr9q2wHZUdQRwABAT5EAJ9fcDAXA+7n6av9/VJr9a/Sb1PnuACfVMEihQSsyol6
|
||||
FBm7vc3S73d+pIq5AQ0ENuOQghAEAKFjw1K+7qwrSngPQBUGxHPyJVdiptGVFNkA
|
||||
dLgsJfDH+LwWZ90hedo0s6jKLjhiu5IKeVl2Hhhaq4LHaaDLAbnz0DNwWFqGaoSU
|
||||
1spvubgX/8QYhkrTNOBbXe1DAb2FNc6Fh6pyGc45oMPA8QrUav7aj/kA2qGquKfR
|
||||
MUUFYuB3AAMHA/9HTT2zrVf8WRRQCHzDhO5rqqd03/YaypezI9iN0XkTeASsryMN
|
||||
wMueI4eqSzBXXtskbzVzMJETklxUUstZAmD1yl6hOk/5hwX6b3CG2zBo4n8s+vHz
|
||||
zyL86aW5IPzVU/7rMGGFNRulrN8sR23ddzOlbsI101vKIRyBP7oKv5bYZohOBBgR
|
||||
AgAGBQI245CCABIJEEE/SvMa/atsB2VHUEcAAQG1rQCcDbUhj2I23rC0k3kcChgO
|
||||
X32YhQ4An0zwuiPl8hmr4xya2h04Ev20gjdDmQGiBDbjkc0RBACKzsZMOq0QzqW6
|
||||
inp5azEWL36qFRWn03pL7GVvDNBlUDgWMKp/VVH0lfx/CMt5ybFPnFOFBVxGqB4V
|
||||
VoLKTLY2B78VwUw9lB5o/mO/kZFZzk+8f1LDym8Y5MHnpXhl5HhxAsMGbkIXm0q7
|
||||
UEJZarYwsd9y3tNd7pALNkpyPN3DywCg31W+so34RtAL5MfN1ZpRal1x9acEAIVY
|
||||
TItU9OkjWM2ygJnTQXwVq7/ZtpeTyZ1E6UllLpurniSx85BDNF4FZx7fmHRbs14F
|
||||
Gn7J6hJ/tjeLSNM7ias6Iv/Q0JxLyoo2cYobWKt0t6zelCENmlxR7Yb1bcWcaHGX
|
||||
pbmGlhz3nnSZSPYfcjm2Z9JixVxWOk1Ih0GLPETYA/9IjW3qrsscxCnSHcw9DbPt
|
||||
1oyFQZWJedWXb6sqNvlPtu9IV1XSLLK7Kiq9Q8EZbAkUsDGPp6wdGVDpby2iAe6g
|
||||
kJHtwvZsrv3yaBg4TGTmAF7GrVUdBBk3V50rgsajYRIqsJW2RjAHMBTvqFgUoBso
|
||||
xTx0zEjsNF0uNne91DcU2rQnRWNobyBUZXN0IChkZW1vIGtleSkgPGVjaG9AZXhh
|
||||
bXBsZS5uZXQ+iF0EExECABUFAjbjpH8DCwoDAxUDAgMWAgECF4AAEgkQMYwfrvrv
|
||||
bRsHZUdQRwABAWcDAKCzaFoiAm79QSmYISeiM7XMKhoHDACaA8CU1j8+20C7rNip
|
||||
OHYz3KfUMhe0DkV2ZSAoZGVtbyBrZXkpiF0EExECABUFAjbjuAADCwoDAxUDAgMW
|
||||
AgECF4AAEgkQMYwfrvrvbRsHZUdQRwABASDdAJ44x/SDfOdtzwgGJOsg9SBTP2nd
|
||||
agCgnp5FlNmTvP6FPLHgkNx5F5BtiUa0EkVjaGVsb24gKGRlbW8ga2V5KYhdBBMR
|
||||
AgAVBQI247gfAwsKAwMVAwIDFgIBAheAABIJEDGMH676720bB2VHUEcAAQFepgCe
|
||||
OpUG5rVkWVJXULaeGZzqbT+2SbUAn3HmDGXzAJ6lCiYh5NrTIb8A7wIduQENBDbj
|
||||
kf8QBAC0pe0mjRH/JmKL3mubSTRMKGcd77+l8psl4GtcA6iqNj3g650Q2xxgW+Qb
|
||||
1iL9SeiIJP8KuEfj6vfPVKZHKkRAfsjnpbhN8zz7WQa2y8kkmqojHoGIh5wAD3NE
|
||||
6ox+1D2WvnySmU1JOuAQlEDfRC5C9hSrQBkO0TUCWL2wquDv1wADBQQAl3TuGt2S
|
||||
CuYSXo4R2dNZpB2ukqqHOj7nnTQu7ZVoi1OtgZYxor/w783GzLJ75PfdQMSd6T+G
|
||||
byq+QgpaiBvlmWtc5rcF3ZgnxiW9n2zUlQ+M6denubJT6/Aqfn7yL9v0sr8K7kTr
|
||||
PqAM0lb6DAMwBkpN8o+Z0+aIpG5/jOtnwuSITgQYEQIABgUCNuOR/wASCRAxjB+u
|
||||
+u9tGwdlR1BHAAEBj5AAnRH+1me1/iHDnS5ltXysOdl24/BMAKCPThApQ7lJe8LY
|
||||
r61+lXUUwr1TKZkBogQ245LREQQAubUOd0B7cFzJHF5vo5NwiMZ1JXPjyNqL2OWE
|
||||
/XfaeJiB55oMmVEPmK1JF69wU7ZBpo1l4PEIWcP7WRMqvBEFl+8LnelRkSW95kwF
|
||||
r3D8TRnarZy3kfiBF1t33dnkVTaZYxCDKOBdZ/ZiRvLa6gZ/KHhITfzaS7h36G2M
|
||||
bAlGlj8AoKQPFsEPjByKYdx72m5/2Ju/4d4jA/oCNAKaJH7N8Y3HLis1ShhpytJP
|
||||
1yC9GJjtec3ugzYSC7RKV3NJcBeCX4om3KhiDSN6YYVICf4wdqz6TAocoqPzR2t7
|
||||
Fz6+upxIgh5WGnnCs2e7uO1eXUCSXONfiDEDzRKGTQjkdvwFo+880DkiGln/qmRr
|
||||
cILA568dwNnOrBio5QP/dbkpUBhqGDr2LchpkoYyQlqzbvUpXJ1xlfZim1jfrmdf
|
||||
sk83dE3iBzvmT8ByIZcMoqDEHil95LmJp3qw1yVeApP/ZWR+0XiBLEF9GhcAOc5i
|
||||
hH2ACSXLWiRXpyMmK2/erTvTX3QkAcqoQ1cFWCwNNCrlgycB84Hdm5GXdajp7cC0
|
||||
J0dvbGYgVGVzdCAoZGVtbyBrZXkpIDxnb2xmQGV4YW1wbGUubmV0PohdBBMRAgAV
|
||||
BQI245LRAwsKAwMVAwIDFgIBAheAABIJEBaEEKSPwoLmB2VHUEcAAQEi4wCfbbaA
|
||||
ruJvA5fMgp3+Bk/T0kL/f54AoI56Vqqpio01uS7SADzj47t3WQyquQENBDbjkvwQ
|
||||
BAC2wan9ScDXLgCqN7CWSRM5B68vC3PCbemYsuOXZjdN8afw2LSHxZ3buRXfYxRn
|
||||
JNo1pm4PGkMQ7ZpQikZZVCZa+WoIVXYXRnYAjxHhvHW0LaQPvnyFS9H5LaGf2Urs
|
||||
TWVA+695zYsSaX669XFb9WbiIMGB4yUiXPvQwUL0tSd+kwADBQP8C3sKWjsPh02T
|
||||
jcEy+FDxWAn4g3LfsOPw8dfawJln+0h9LA0hTebbKBJWt5OUMqjjTq/pCZ5+z+b1
|
||||
0f2WwET/xAvjQSTdJjrFX9DNNU3jhCCelEpal9oxsbNYlVd5zOU2RN4hlmj+eEOb
|
||||
5oy5wy797sQpsbrgGetCTsvPotIpvbGITgQYEQIABgUCNuOS/AASCRAWhBCkj8KC
|
||||
5gdlR1BHAAEB9+wAoInApOl706hL9+EV1UpIX/hHAxzjAJ95K6j3OWXkiRmu0X0X
|
||||
FYZuULXL8pkBogQ245SxEQQAyG4mRUQZagjDgl0xAnaSbLCQ5wJqYq/snwCl+IbD
|
||||
lXcoHqXQNO9QJrPKwKQAUv3Nvk7mqZWnfMPoskLOASrs6nkCv2Fo9Aw6smNizO6i
|
||||
W7xXepwvxjho4hLnE00oGPCDhUnAU05LO2pTBoxwHVs0o6vtaaViXk0s6dOFCoVd
|
||||
f9MAoLjiGlK/3DFWoUrqIiuE3aLfgkddBACrp1snJ1BtiGhmKjt7An6Qoc5LVnU4
|
||||
1J/REiQIyitUFAvPX+fiqzDyE3VD8qX/vvTLpgZCYvvEdBlSfM8IcCn1/Qh4aw9J
|
||||
HzuvKQg8WclvnQ8zq/7RV9J7h/aS/KIhDJIpGhi6YfjfjdSKfLYYfr3S4TVK9xD0
|
||||
Za3AH7/lrTqW8gP/fpKWu8fJyJ9kqHyYrI/j4ykt5QKBj3tHjqCv7FQb4FY8txnN
|
||||
3fLzBtva/tlkSKRsLobixjZUGF+uQR1dTCv042LxZ6aEUqrUytxqUc05pCSAvEZV
|
||||
8bX2H/5+ulSwdxKEzs1h2NvSTAiZ54zzKGjHNmEitdAaPD/9u5xdAiqPFxG0KUlu
|
||||
ZGlhIFRlc3QgKGRlbW8ga2V5KSA8aW5kaWFAZXhhbXBsZS5uZXQ+iF0EExECABUF
|
||||
AjbjlLEDCwoDAxUDAgMWAgECF4AAEgkQH+j8bwQllncHZUdQRwABAVpYAKCVZ7Df
|
||||
K+i/YZGyEu18DnWq0ixligCghGwDoMGgLnenSjyShMZ+1Ecekia5AQ0ENuOVEhAE
|
||||
AIMMgk/e8lsV/KEkd4/jNK4yFj5iy/Faon800I3GUzETuQA2AT3getR+GuV4pbZW
|
||||
E/80b9hnNW50UJGiP1+SXfVtY5vT8p/gNFwn5d0O/pq3bpgFRJmoawTzx8SFDwCV
|
||||
PHEcwOHE2j5LvfrvRBOyKU32tr976ri+Uowt0+92LuA7AAMFA/0Yo9dDqhjR2UoN
|
||||
cYfEZwWhRHaaJenP3z3QbzjJkASb5H84xCTEpv0dqEtVTJUoIo8Lh5VjbiCwok4Q
|
||||
PLVSbQFeHqTKb7N96PjevkZ1Co6OrLCNOcPRvXxgCwSGbuuLMkQJEutnXLu0DOKq
|
||||
uY94KXXh79La7lTgjReE/1Wzbgc1+ohOBBgRAgAGBQI245USABIJEB/o/G8EJZZ3
|
||||
B2VHUEcAAQEJeACgjmiKaxmzxkqYtvmw8HgBnOeALLMAn2iD2ym3cRhcAH3leZ/O
|
||||
qAkFG/ThmQGiBDbjlSURBACcp0BogujMnThXpn4UjBARj9oXgQWskkhz657AXu6R
|
||||
mX/u5RmpLGqbNmNuqKDIwUbJslIxrpOnA3QEobkIl7ThH+ZUIhGzPUnHlhd7M3dQ
|
||||
Ww1U0TfpHyXx3FYb7CCPabrSC7hWWh1ylUxz+RGJJSApR+D/GY+dF7dIllKUbaUG
|
||||
bwCg1z+vkNbzqibcwdYrwCjKG9VeFa8D/A5yPHqB9NMp+3OlAGE4XRTR8LeelALp
|
||||
u+MuNMGFCMLdZfmt/Amoyau51FsQ7WwWrNM5A+1v3Fq0x5WpNw6Lr7HbN9d6zidN
|
||||
+L0uCrXPweET8ueS3DFnHI945epe703TbcjJBO/uYLn0LXExmTg846/1ZlQbPgLz
|
||||
mzb/2JMkJ+QzA/4xFbRL2YeaKyu4JjpMNUVzXYogUwg9KZZq/qBbpsIAD7Agd+Zx
|
||||
LJHoweItXaC0nS9C6qDJZ95OJrE+h/Tt2D2lmxXseTVlSESaWh45x9mbC0eRGFYY
|
||||
RsSx3z0hYwMmXA0ntj0lndC8ru8HjZtBW/KF0VB0RcfSyW+W+yAq0Jxo5rQnS2ls
|
||||
byBUZXN0IChkZW1vIGtleSkgPGtpbG9AZXhhbXBsZS5uZXQ+iF0EExECABUFAjbj
|
||||
lSUDCwoDAxUDAgMWAgECF4AAEgkQrRsPrUPC0McHZUdQRwABAdUSAJ9ZMVrsRsAk
|
||||
tfouxadXBc82Qh8nCwCcCavkRu7sfbEBJqKdldpinYwWZpK5AQ0ENuOVSBAEALmZ
|
||||
YtP72G7OodR4RfR270RxTHj40PfUpPIf3U8ezyO3kqjB12IdD2YIXIZW6zEj53ps
|
||||
X8DGya5nSvVjdFofQSVHtsnB/H7VHBkaOQnREoInHs4helYOD0M/RZcbRIb65e6v
|
||||
Eesuzvo9N0ACSlBsAXbeeNKGfGGCog74GVGcZ6HnAAMHA/9W9n2MwJ7lq0GV4V0E
|
||||
OHDVcTAVRSh0nB9uKBVW7hFi4DP7XYBfgj8Nlbc22vMkkdSvNFUoLEH7Op9sMglX
|
||||
fiCPJSh02U/6XyAhXDyZRyrOIHviTZ9SHMQQIqtEETVuYRkzvSnSfDBVq1p9gW6e
|
||||
ZN9q6AM7gmoKInpRaODFRWU7DYhOBBgRAgAGBQI245VIABIJEK0bD61DwtDHB2VH
|
||||
UEcAAQGO/QCfaGt8NeCm0zbssmOrXZ6v9zFk8xEAnj3SpjLTyqemniHSJ9KEzIKJ
|
||||
CdiDmQGiBDbjouIRBACKncc4Ueec7dWaVARy2SmNVufeSenYs4AsIPP0v59jEl7J
|
||||
I0rb+4JbIJoAzW/hcm26GS/UbbpQwig8/PgMUV5QfBST4CEOlf7/x2a4HKk9tDV4
|
||||
An7q2aNr1beW+twxfUGWWV5I0o1b/iKVk/LiQRiaMr8pJXY266m6/2Pn9LmDtwCg
|
||||
+Iqfx8gsK2PZCWv87uEKAOLzHXsD/1eRxLqCt1hT98gdDLykRTlI3kMq6EK3I+z/
|
||||
8pDIMDuPIJq1eM68YdFZr8s7i1ye1QpDltPYHgWnUC733ujAKANdyybm3HrA3TSB
|
||||
jEAhNfcu8nkrVorvASQUDCLJatWRWJTUVrPH+GXIXMA/Oi6LDsgNDOJanwzzvDCC
|
||||
m8hWQqW9A/4xYAZ4NVFrQq8gtQPJWuMIfSFSvpZWNgQgYZntiXSUGYOVs28T/87R
|
||||
oRx02tsVDw2PA8z68q/XRuM9NdetxbUXQHB9eszFLi3W1idsXhd/C4SyiTgEFXG8
|
||||
Y8s94Eadgk1PAYHN6Gd3SY7jmevqYGVLmBp7qfj5Y9XSM5SE0Th+fLQpQnJhdm8g
|
||||
VGVzdCAoZGVtbyBrZXkpIDxicmF2b0BleGFtcGxlLm5ldD6IXQQTEQIAFQUCNuOi
|
||||
4gMLCgMDFQMCAxYCAQIXgAASCRD+GAsdqeOwsgdlR1BHAAEB+u4AniJTgzmzXGxm
|
||||
JdrTAudfgUEGX1puAJ9+U2nDISnooSEoI9bA9Eb1YlzSqLQOQm9iIChkZW1vIGtl
|
||||
eSmIXQQTEQIAFQUCNuO3OwMLCgMDFQMCAxYCAQIXgAASCRD+GAsdqeOwsgdlR1BH
|
||||
AAEBGuEAoIrcivM2owTqgDdGWU6vHzs4IhGCAJ9WRH41/o3n2VLmPuMxc66Tv319
|
||||
DrkBDQQ246MHEAQAlUnV8VFpc/NRY6h4EeG9RLZoZlvPQpqbB3ypUsJWLwbWwf8u
|
||||
0xSH7wK+GRW6bqnsOib7YyBGaF76JU1sB1TxBZLhtCwGtN6JWmKcwumQQ7i5G9PU
|
||||
bpAg+M3WOscGwDEbDs2YL+fey2V7Tiyy55jsk6bI0Qy87VrLjYJZua33zk8AAwcD
|
||||
/0slWbxRHRFZ+f3UE6e3gLV3a22RDN+/XLQiduut0W02XeeZSAXr9X05ykJLw02N
|
||||
nufMiEOBPjc6/faoPQsn+ntzoRK01KhATobrAYHuP+xOS6yFTL6OgBVPaoJ9EoLJ
|
||||
7v8MNrcVcN1xI6i/B4JfuEP+e2EbyTnvqtvWHvSy/HmoiE4EGBECAAYFAjbjowcA
|
||||
EgkQ/hgLHanjsLIHZUdQRwABATK5AJ9pek7H6yt3ZHAJ+7nn7sGmxYxb5ACg1INF
|
||||
N4AMzqEUjbZ51KTVdAvyKlSZAaIENuOjhxEEAN5nO1c81jCmgh/oF+p6kiZmqFV3
|
||||
ape5kEmcS/BoWgCXt6vjaldctmFYi7v+BY4N9zI3GxQqAxt5D6dY7aN1xlC236CZ
|
||||
EAaXUXktvGw/ppHDjdbs8CRuZiA9jm1j92GAUY/mm6hX2aGKOkVwr9yN6DrA2CaO
|
||||
4SwK/wEXkVfj+nazAKDCaBzHzwSkkXf8QOtOTj/xevpnzwQAv30laCeXTDZM2I/1
|
||||
Pdzma1V1xizfae0kfzZOJBDQtHQDvNFjmu6iM1kL0uxOG3krr0AlqSsMD8W7mavb
|
||||
FigUlxbhvuul4pTL/BiJ946FhjlPY0Ni9pmdAldno7yUYsWADEKadkQ3ghEVqEqz
|
||||
+ACYbzp3p8K+5KuiFJm9D4uyvToEAIVPi2N+4voxnRWGwKXF4E+fLYAzXT5sMMzl
|
||||
46Xk4Ms303F/5JG7kB0iiPPY6oP0l3nlahulRcbNMj7SDbfrfoi4m4ftUYIX3acX
|
||||
CSN0gNuVGipg8CwlGQyILgWRFp6oXQOmAlpxhIGcd1jdh3sj5y+CQrugGPNOJT9m
|
||||
zmFkB4rxtClEZWx0YSBUZXN0IChkZW1vIGtleSkgPGRlbHRhQGV4YW1wbGUubmV0
|
||||
PohdBBMRAgAVBQI246OHAwsKAwMVAwIDFgIBAheAABIJEOup8kDrncnmB2VHUEcA
|
||||
AQGuJgCgl0HAxcZVFMWV/DW7heKYJE9UVE0An1YVfKzHS6BZohosne3I1lAdagBG
|
||||
uQENBDbjo6oQBACPtZ1o4mPMk2zYbyu+sNm8P+5oAtD0+129gCn8OunvEwflPrb4
|
||||
opOUp07ezwhAE+K4Whwk2Kvmy3+ebxeX6Bw5k6+2vjlz9yXnh8Y7WA6MFk5+BuR0
|
||||
FUr8szC5BYh5srioJmcA6UMtg0ZVSC4YucRAFJ+eGGSCHRYDSSq3t9i+lwADBQP/
|
||||
dw4So+Ux1h4ucYQbjA/G3JUhyHAY6/RhFblqlvPZ907ui2PUAVQ3lbMXDQDn5YfN
|
||||
rU4hSGDnRlyjoefArHoX4ttnlo5zfsQC9oWA+4zEF+RpZhqAKh/eMEXQJtNZRdX8
|
||||
Pn90WYh64ZO5Qw2wZUf45IxbaEE3/v5okrksscv6HOmITgQYEQIABgUCNuOjqgAS
|
||||
CRDrqfJA653J5gdlR1BHAAEBc00AoJq+Jk/8DzdqaYOce+RN3F5+qgdvAJ9oTv4Y
|
||||
CD5H/60ksnQO9mWXPzFjOpkBogQ246UmEQQA3Vs5XdZcg1g6hj0sxjrHoV8k0mtK
|
||||
Tn1Uy3JKSaQ6RK3J/I0vHCq15FVKMCO0pWYT0ZmCPuaahmhuRWeVSXdU3ylooXOz
|
||||
viQx6Ct8mpjp4ejhUBT2VBdflpQBohVy3Pljg824DkjMv/MlwOp9M3vr93reZ/Ss
|
||||
4m97Axo8OQzJomMAoJlMJ6H6rJB1b9UurQ4NPJlwCyijBACFRsn/Yo9wczW9H1WB
|
||||
lDi1NO56kN0aTUD2irT0KQaG0ZJ0P2Unc7ogC3AgfkOuuH9XChgPjoLZtC/39cVJ
|
||||
ikVt60/ZczLXAsupHLnQiNjh5v4DnD8yqo4+aJ6Q/OH4EeAXW7HoU/Prq5sRYiv2
|
||||
xRSOngtS+XnQUHES7O0xdo2N0gQAnV8vch4Oog0yYcrL0e1Li1hP9bPcrIq4WYD2
|
||||
9L8iBcB30czPegGCD6S2a/475Kw2sE8WBnxiGa4+1Mhnj7u0QnhUVVV+eQenrzb9
|
||||
3wKm5sENRh01+1hwjXQJD9O8k8Wf8J2bnTwM0MEZBH2d/U3XHGzoR3x72790TUNF
|
||||
cW1rUFK0LUZveHRyb3QgVGVzdCAoZGVtbyBrZXkpIDxmb3h0cm90QGV4YW1wbGUu
|
||||
bmV0PohdBBMRAgAVBQI246UmAwsKAwMVAwIDFgIBAheAABIJENS/V/NzcuJDB2VH
|
||||
UEcAAQF3LQCfZhlov9Ux6LofeSt5g2hVijDdX0gAnRc7adixQ2hpprv4vNoKvmum
|
||||
F/D4uQENBDbjpVAQBADfVCPYwZ59MKgXTH4P71QzFnpG4E/MjqDNfW3NxQ9ZjLfw
|
||||
0ir6U1gGDuEsWRR+fS5OwCbfeHZDzPj8MZPuOZBamgiDvI1OvrrzUv+BijkWGEL6
|
||||
oRFnWI8zJ8zDAPuuvP1u2FQZOoKFXaHo2I9Q8zuJz8P2vEkgJfLx2yiPR1Dp2wAD
|
||||
BQP/SCCKZBNQIaY0cfKmiv8ZjRcAAvhXLyMCwLQUfVRqoNVOtMMfWpYtGdL27ESw
|
||||
4kgZIsxJ3ELQVkRiriMKbsJiNM4dMe+9gNuGz1CG9b2vhUPZ59sREVIRgyIfr0BJ
|
||||
AsYOn87mQ5lOBA6+XmjHO+ys4xpEVJZyfrq5QAw5GYcrPWCITgQYEQIABgUCNuOl
|
||||
UAASCRDUv1fzc3LiQwdlR1BHAAEBjvkAoJVm6lRsxer3LDTczfhFL1hP0zMpAJ9S
|
||||
AV34Wfz3GpTg7CD8xDNiUut5SZkBogQ246XaEQQAp44vakh1n7NC16HF0v2X+4ME
|
||||
VJO432stvwOAuLDxn2PxTkIQf8zfxbMfWccoqVkqMZVliLKFF8AbzfC8edPzeWr4
|
||||
B3SWBplNHjPqet3lWI6Uc+V+qjhE9k/M9764XsR8OXv3awl6tcYBqwuiyYqfEoDI
|
||||
nJWOHt5lyNNL+FSE73MAoNXIscn+BCUxiTy8Tldgvs/Dh3bzA/9WwpWSOXGxelys
|
||||
JAigp4NeAo1W/0v7Q95uynOvZY5qHyIE3VA6Ru17EgoJtv2aa+ISclTQUXHkwjDi
|
||||
aKm9jgSkJofcxwbAmkLNaZ3MgPxnqghJTIqy4/s9eOYBJuiBXoirLab/ZEO19siV
|
||||
vCi19uI5P1Ovcg9sf60cBkHIxHK/EgP9E33RY49Kk4PGv0Af1u2Z4kPQF82333XX
|
||||
r6p3C9atOh9xuQGDO8Hfi8ssNowpUjKKfHPaVjILtpKkDe7ONm+g+8+tAkUsTR3H
|
||||
sNKRRO1ZtAYHJFpunKtdh0pnOwVctv4tJNbAXexAtrHQLhxhPs4s+XGMNWr8DSOD
|
||||
O1plVZrfshi0KUhvdGVsIFRlc3QgKGRlbW8ga2V5KSA8aG90ZWxAZXhhbXBsZS5u
|
||||
ZXQ+iF0EExECABUFAjbjpdoDCwoDAxUDAgMWAgECF4AAEgkQE9uWVTTG4/EHZUdQ
|
||||
RwABAezUAKDIVCu3fJltReOUKcLaW5/xHUrqjQCfePhlWOhq7TGwPMq2R3g/M0gH
|
||||
na65AQ0ENuOmHRAEAM6TulLgllqT/bqeRlYSz6EggX0iAPSVpuQKev4Y0OYYmuwn
|
||||
EvBONT42hpej5IeZY9qpElAWvPdkl8kDGKjKhKv4e/gVu/p+tkgkTLWDh0WGTwOI
|
||||
b7NHe485xkJTLJbce6mpqFTT9FxfsLNcBy48kJd6jJ5KwEPJQCT/o4Oz+R6vAAMH
|
||||
A/wOtakC0V7Eha+yzAZ2lEkdKOvuPxwnYfLfppwHkAQwJJ3uQ0z4sKs6rI6GHpF+
|
||||
iSu8JPpm7CU3f2cOeSZKvcVZupxFKPySGze3D5TKnwi2qEvrbW8WfXzQjt1kzXVs
|
||||
QK/5hmWYgX8vck3MVH6Oak4NH31suNAjR2lSpPoiHJLRs4hOBBgRAgAGBQI246Yd
|
||||
ABIJEBPbllU0xuPxB2VHUEcAAQEmaACfU+XRhr/UgvgCfMlOthY327vlI30AoJyp
|
||||
WeGLup2DqouZIGkY8bmpDrz9mQGiBDbjp/8RBACXrm5v2sQpLtexfA2S8a2PUruC
|
||||
eqXYfVsnkYX1sYJaFaYHxYW2wDL1dR4LdZuty5YWBOxu1N9dnkjuPsdIbq6R/phy
|
||||
6xv5sDUihP4YBAZakV5ahd7XrBdkWXSkRzaJSfH1OG2hAXR87liVu8ck8RDeS+ip
|
||||
x1vnZY45864IAnFzqwCg2qjnDRjGAn2OSPsnhyZH44VQQpcD/A7SOu9gTt6Jl4VS
|
||||
MY2JGi3HOFPOHnevG3Pb8NYbcP4gEU63iqrHGndYJI07lKcFlZRbnSEOSFPFLuNK
|
||||
ax88GYKKeZDoQXkVoU/ItAGrS4rCExpZ+Jx2tBL2zJcWU+7NDmM5LeRUDE6a0N3s
|
||||
IxMLzz3Z2PTarMATjpA01Qj3WRlcA/48g1+gnyFXbO+UZn21WWj4uCyXUE6/G8SC
|
||||
ZhXXiDJOYxaBrmw2rtN0x1aLwXPRXLuwjhL5Ewn3qszCzaJPNYuLaMY7jiK2ha20
|
||||
LCqYYmaVJa6tGy9iFIGC80ItcUYZpCfmdw7W2oqdZIN/rblScCKmyBbw/gCB3mol
|
||||
mLBd8nrseLQrSnVsaWV0IFRlc3QgKGRlbW8ga2V5KSA8anVsaWV0QGV4YW1wbGUu
|
||||
bmV0PohdBBMRAgAVBQI246f/AwsKAwMVAwIDFgIBAheAABIJEAyCDHHSaZMTB2VH
|
||||
UEcAAQFA9gCgpEHwTLc3LpNopoagvYY0VATAzUwAnRZuUrRJxIpubUE37aF8OaYp
|
||||
GSC9uQENBDbjqCoQBACR2VIlh9OJkf8KR9Xy2eEjogPP5KCJkpyd4QGc76EAmi20
|
||||
BEYCiN1tRGU4h5mpEKAql1NcErsx0cDPhEoWcABc8MFmADmr4KiqfnzS3878AoZv
|
||||
yQqf2fnbP2ULwDkqcdpECw4pXI9MhTm+roUuaxaYwHnmLPzboOT2QyFXuaZ1BwAE
|
||||
DQQAjwmrcmep/QeqppfsJm40ocmBqDXhtNoHDSeJkrQpIHoUGnOK0SjKy3kkE8KX
|
||||
RrJATDQefiOFkCpxnJsj/+kLUI1AEE7jtVSLTLVRWMTG1o2aZbG6DOTNYcfHhabJ
|
||||
awJDAY3gH2uJTCziDd2ALTTuX5qicrOPlASjVeKIw1MUWY+ITgQYEQIABgUCNuOo
|
||||
KgASCRAMggxx0mmTEwdlR1BHAAEBj64AoL6wmTv08Y6txelPb8XUKpayw4FyAJ4n
|
||||
eVj62ZIfdX94DPkF00H5qvVeEZkBogQ246jdEQQAwVpm5pgcsPrtSUwIscY+TV0V
|
||||
0Cfcy7ZMUUNRh8S0D8kM6I1lpw+JBJnvMr7BV7rpWz1/M2TJ5eqnAvMLfm+RPHQr
|
||||
Wbr0C970udchnvTO+lUQv9R4K4hNGKhzE2CU+Cfh3In7ZXRxYnfo0ZxmaS8FbS8Y
|
||||
i2lgJukgYvNhU5+JVRsAoLY3N7v0jLD4MpT0cjf0Hh/PzmeTA/0dshv3PmReJFnI
|
||||
Jpc4ycUFDdsBmHg6DllDF0vJn+shfgy7cMaOqDpS2ix1U0evqh9lYc9c2qpNSK+h
|
||||
SY5LlBrx21RbdgZry9ukrU4yeMwuFBUlmD96i732z04U/kaA+HmvlXD8RhBnqrNL
|
||||
piJierNK3ktyiUvb4B7RqNdSLOJz9QP/RM1e0JF+RLhJ5VKRldqtvWhmMd0aXDoQ
|
||||
2IsaIDR7lvivSsHJbgRBAZk++DcMVcyOqnSVVWZ+ZcU+CAuRtM/5InX9UZIL/BKo
|
||||
+QyIpIJ6dGrAfBYh0rG/t/XeHJ5NldHs/y5pJ11JdpqSqZP32/ql1k6jw2xVBPHc
|
||||
/M8qkRVyI8G0J0xpbWEgVGVzdCAoZGVtbyBrZXkpIDxsaW1hQGV4YW1wbGUubmV0
|
||||
PohdBBMRAgAVBQI246jdAwsKAwMVAwIDFgIBAheAABIJEDfKtR+3kQP4B2VHUEcA
|
||||
AQGKXACgkZY9/w96yK2Oiq/MUs/A74SzJ2MAniQ2eSHT5CQ4G8PPvYfPZueNI9PT
|
||||
uQENBDbjqPUQBACn8JyfkTPFcgaWMpUpnk+nTEkDe4GhAG9fO7alTgdT6+aDCdfX
|
||||
fXfH7gGwdURvDv6V/KEqcMPRNLAgAeP/F4T6OtoJNTxfWLB7j14DJNpYXjBPJPN1
|
||||
kpD2at8GcWB1aVGMsAtxMwlo4TZlqyfzCAAQeCLhBbIE9LWKX5oUTqiLOwADBgP9
|
||||
Gm8md+/xWp9sLE5i3uZ4t9Muu9w+UY3Ke/WcSA2CNthEYhHNtcMPP6PBwtz0x425
|
||||
mC1pe9RuxDyzRfV0/q+rjdWZBNA+VTVNDHXSj5hifvem3KFvA6TIgMabJ/q4WE7T
|
||||
4Hn8xjQpEsLGjSXAzG9WRg13qTzTilIk+rC6xYGbZHSITgQYEQIABgUCNuOo9QAS
|
||||
CRA3yrUft5ED+AdlR1BHAAEB/m8An11Axzacylwq4fbzHAqXyvsw/enKAJ9YcYoU
|
||||
dYgORS3xF8cAH2B5q4RBIpkBogQ246pkEQQAotQXkaoExYlC0GzW3VKn40g4a4wu
|
||||
Ak6Eg1sxTq2TaPN5S3qig135zw/RN7GxtIRPCGtTie2m8ghJvsjxPCFyV53tuLko
|
||||
IAEk7PPsXD5h3GjliObUNAfv6AS0/HefgCNlR9EA3SepwWLMOlFg+pVo3VBiIZaf
|
||||
3I8Xem5tCFWfzPMAoKnHUtSVCXZ7m3VgmGaibarLfwR5A/4gHjkUF8N/koq3JLrh
|
||||
qVDS8dgiyxSnzTo9CivD9k66iKxxRCP9Z5ni+fusJ27rS5HUS4ekanufS3uKASAA
|
||||
5zEOOvEmamBJ0Pv1X6gkAUsBOjaayPUiSVW8l4jtmwibI9yEhTWWqf8a+kBqb034
|
||||
WIgHUpQwWpMnNzrNSfVCpqDXDQQAiJEc9hFbyiN31SHgR3dfR1oCcKXIxYvza3Zu
|
||||
P9slGaG6lCfhpUnkPSkUH2LNOIkRZyIemqIx2yL/MTFhggNLVm73j5YVs0jHIwV8
|
||||
esnl9RC0CotvsTkuuXFk41SetHCyGpHhfZOZbabPVainnjZ5RDVRangavdWUfqCK
|
||||
zBjQKdC0J01pa2UgVGVzdCAoZGVtbyBrZXkpIDxtaWtlQGV4YW1wbGUubmV0Pohd
|
||||
BBMRAgAVBQI246pkAwsKAwMVAwIDFgIBAheAABIJEL55SFK+XPiGB2VHUEcAAQHx
|
||||
IwCbBHwywMR+PbPZX9J6pReLXH5aa/8AniSgj+olcL4RiHQrvg273+s/P7COtBJN
|
||||
YWxsb3J5IChkZW1vIGtleSmIXQQTEQIAFQUCNuO3twMLCgMDFQMCAxYCAQIXgAAS
|
||||
CRC+eUhSvlz4hgdlR1BHAAEBmdUAoKhrc+z524neflMpRwJ+NG8KVxOxAJsFZqm7
|
||||
bBtYllrdcTqNqMk49LfBObkBDQQ246p+EAQApnvWjY5rMvw9Ly8xFL49pGjAYFb9
|
||||
zFijvgG4tMirI3T9EBLflKLJ8m4KWoRoT2eNmy/JGLHyZjveaVh8TerDV+uxZkEG
|
||||
vv702nz8NOElQTjHWHoy0n6poci6FxhfJd1bnOjDK2mZEufEQNSn2PhA46gjCLRT
|
||||
APuwLpitSSL5ubsAAwYD/ij9KRO69/Jx3+W9DZQxWIQBiKnYHVr1us2WpdpTV4jp
|
||||
CqJOCOgB/hlBmCY1C1/tpsAj1A3ZZamJRWVZoNokkReItZLXfGacprGbmmjcg89g
|
||||
FM5V3nEUNCU/mm2BQWp58h4NOCv60dGr5GAqHDxAStPk388zbxEdyFs57CPQ4ZJt
|
||||
iE4EGBECAAYFAjbjqn4AEgkQvnlIUr5c+IYHZUdQRwABAZEyAJ91yirChpNTus0f
|
||||
QFZphR8KtDpOcgCeI37JBoFvBkcxtJoNMFGd2MuCWwqZAaIENuOq4xEEAK14podn
|
||||
ulwztC6PwRzxLHR8ne7Q10uyjnGf0STgVYwsG7qPDtv/kqMHZa1c5lJYoc7N5N9Q
|
||||
DHv00womsP2Nlb/SQQAVV5mnBkXWXx8GxEQtH1zEBqMTdG8WSAJgCFewXUmej6qJ
|
||||
TlM29p0ZThLOY/i86eeOshZPLzea1mLCgUhzAKCBppoKUTxDjU3Ih9W2NLd/42bz
|
||||
HQP+Jwf27Aze+kHZBXb0ggGprOBoWvu8GiiAWgCWVoJBs8uLIdfUyTeQRmDnF7CY
|
||||
NL+1TisaqPtRwv06VnHUgIPxynzTI1h+gjsrlczqxg4yZ8k5EY4Syoy2hhujeWW4
|
||||
OAOSDboNk3KdR4UdlGshbPZwqpO5oHd3DT2bywk26zemgS0D/1DUoOyMo+Lz7aRT
|
||||
MmgrdXrVCCVcBUOV/MroHko4RnoZH+Bf0zm7LIuNETJsVJI0+W8tHXX6ZXgZHkBy
|
||||
tVA6YTRCkXKjUyv64OxurCTMRG9GrWvmk7KozlY9eGVdrmijidrV8ERfvogTMrrE
|
||||
hUbTsac2dpj52U+Cwurgjz4DbRkbtC9Ob3ZlbWJlciBUZXN0IChkZW1vIGtleSkg
|
||||
PG5vdmVtYmVyQGV4YW1wbGUubmV0PohdBBMRAgAVBQI246rjAwsKAwMVAwIDFgIB
|
||||
AheAABIJECWwD9QwzsaEB2VHUEcAAQGY2ACePRDTHz8CtVNREhGEEuWLbN0kXAIA
|
||||
nRuuRt2VtHZ4Z40AIX/75PhLXjHyuQENBDbjqxwQBADhnHlYNzwuhbYK2a56H6Ic
|
||||
1p7ouhVQc3motQ2eTDCpnTev0DL9Xnh6DDm993234cAOdZ/pD7oWqa+kKk88etkR
|
||||
gP4CtZu741Njn2MUjuuRjf60lFzf5BPN40ex7seDKHEV2fv/J4Ki+yQI8NS2XScj
|
||||
p4iaXkb63JDzQv2ymrmu+wADBQP/eVYwIySAFP4DjMLW6k4FfnJh3udgGtQiRGpV
|
||||
fPMihvOp56h7i+McVE02ZY8o22ypXiQ/wIe0dQcQYUhA8vFrk7qJxFR1cU3C/WIo
|
||||
OKWfzs2GX+X5JdXizWki2/F2TE9CWz9Nm//zjKQK9vZXGoGtaNUbVr65VMiGDk5t
|
||||
kXE8ZH+ITgQYEQIABgUCNuOrHAASCRAlsA/UMM7GhAdlR1BHAAEBIOcAnjt0vZDn
|
||||
9+3cTNpCuV1ZKIu2t410AJ0Y3CnFBUFBOKk6zkOJnaArwVN3ZZkBogQ246tbEQQA
|
||||
lWieyQhDso2ZnD2wb+gq6aqk1rRUhcwdBwCTbiE1aLAsnuMl8nLH4fvhaTz2V/Ae
|
||||
joL00e28duA5or9JiBfmVblrpTAIGWsu0AU6uEQsWgZwRdso3NH/KfH8Z5lxwJtk
|
||||
Z/hlAiEHohmGoD38mJNsgnm63RXadUH76irO6McvWlcAoONeH7i25AcrMol4O7BZ
|
||||
wqGq25ibA/9IRhK7AFhfgaRrDTz84PaIssxp1dWKalRruMJYGQK2LDuEl53Q+d1r
|
||||
nYBPliPbjWr/9Gkjx3K4B0CfWWQC0sUl77bNRFqr8FXkjRZcvkCoxxHG7PIFG77r
|
||||
Ld2SiQ+eS+dp5QijuuMC8skkvQuuxS6eIk0g+jjGlNhjuu97Ya6xeQP/Zxek37p8
|
||||
P1u9TTmN7nPtlzGXGrfKVi9DtJ31E805ruXFqTuoFfcOBRrtfY+DOebX8RxIwQV/
|
||||
TEmyxwoXdmkv03EYwD6AJSmx3WuVi5/revcH9nfSEHDy7sFC8CBp4aavAFRQNrho
|
||||
mSB9lSm5clGLZiD4nljF1EFABwQFch7HhlO0KU9zY2FyIFRlc3QgKGRlbW8ga2V5
|
||||
KSA8b3NjYXJAZXhhbXBsZS5uZXQ+iF0EExECABUFAjbjq1sDCwoDAxUDAgMWAgEC
|
||||
F4AAEgkQX2NWum2XMqwHZUdQRwABAbAvAJsFPpRP6U1YyH+PEW7+bkPLaozCkwCb
|
||||
B48G7tRKLpNYppdhFIvbLLAlHQe5AQ0ENuOrjhAEAJ0LVdE8z0IwWuBVS+KhTtJK
|
||||
F98ueOBYFneGps5iuyC1d+5B2/qUCLGc092eT+TiaMvzDWmpuNSZ+ZumlUPHOyKJ
|
||||
RCUlq3MYN9TWANzuSydekX+/OCFu5zLwc07RIeLe4z8ZcLnviJnWjFr8DXh8qcJV
|
||||
hPVOGpRrW6wLlhBcebgjAAMFA/9/gtmA3d1sviMupccM2kAgSOJNspfEMoc6cCh/
|
||||
//hITSalo1Ucu7efEjnsK1d9IjaQxBKb/emqlMrNoGUz8JswAlRqeGaUs8BENwn+
|
||||
FBwO0GwXmcUbvN8t97RIHCCwzUfEv3rxW9rtaxtilJr3z7cdIO7L1XCmEWnuLgdu
|
||||
cJtIrohOBBgRAgAGBQI246uOABIJEF9jVrptlzKsB2VHUEcAAQEN4QCdHqwqMSra
|
||||
XNfOIi5KeZKV0GpAxh4AnitllwOYEzlC37ZWnV2Z/LTaFzOgmQGiBDbjrEMRBACE
|
||||
EZiYbCZ4jYv20X3/2Bq2fWhVrfNRvd1vFoVedaqvp7VB4FDWOeWMqLOFyzmtrUvi
|
||||
vMz+l9eRXrFQT2CEGuQSAtdJgLC3yfta25xiT7jQQNlNjKBGkcaPybV0P/+Y4k0Z
|
||||
WMCw0Zwc7mjAj3bIq73rviQcOd8rUcI8Hu5vw9Tz7wCgqdnY9RbQ47m0ze5AhdKN
|
||||
isz8BNMD+wYpkMV8j8Esxqi2h10hAbIfODkE8TyPfAV4KtNfefwNQdf6T7N+enri
|
||||
paqHn1Ex2IW44jGG42U/gOo7rnX+wNlHMtNxvBw2eJNX9b5s649uPusoBgXMU1a9
|
||||
AWsHogtQ8Bty40KCdXLhcUUPAWCQxiMD61FuSXZZ81tmyVn3clzqA/9Eu4hFTfbc
|
||||
ZEiopXTnj9WHAwg/DDN4bxfZFHPtYW5oq/EjmfyGCQMkDfo/pmFrC7irWfxfaaog
|
||||
TU1x9o1gk6pXTg/2WMR1SQAEZ5IlRusnJDC7MR4tizzwSvMWnJNMvdpinu82v+34
|
||||
VYAkUrOzP681G81IciJx0ssa9kmG/vJW7rQnUGFwYSB0ZXN0IChkZW1vIGtleSkg
|
||||
PHBhcGFAZXhhbXBsZS5uZXQ+iF0EExECABUFAjbjrEMDCwoDAxUDAgMWAgECF4AA
|
||||
EgkQXRXgHT/xMgYHZUdQRwABAQb6AJsENGQmK4nUrwcbtZ7+av5GDQ2T4wCfYJaV
|
||||
2rBtTR9aWTRQfZOQoIkNF8+5AQ0ENuOscRAEAN5hO+fEhqW2pX71oSUqW/TRHWSb
|
||||
ybNc5brQ1tzgTbheHiG/LQJ1lHjtZoZQsyW3H/efEuNARwryo4IjvK0nmiQsqZUR
|
||||
1795XTIbo/waPN08QujC26uWbL1pYL5yQarwbKOoyAst4jgE1NpZVc/r1+WUp7Nu
|
||||
EapicVjvFNzkiVCLAAMGBACWQJYr+h0ozr7JQ/BqI8vTKuVXb+DIBQjuSzN7Lvai
|
||||
IqMqb9ZdfNNmZ1Atvklo2Ce2VMyliQzVSTZuHJQbfrDTBXBf+Q+AINiHdZEAodzB
|
||||
vDv6p7vsTnoP+A2bS8l6xrWObKt3Ky9+GUDkqW3WuagcUKogQgEb/FKec+GegwSg
|
||||
UYhOBBgRAgAGBQI246xxABIJEF0V4B0/8TIGB2VHUEcAAQGThwCfUj+Oa7sVKCCW
|
||||
H1o+ZVgDDsdZAwAAn08A89d+q3DNrojy20Y8tg28QCYBmQGiBDbjrNERBACBwiP8
|
||||
Sjw+siERrEpyNz101v3/QFncHEGTvH1rscqbqjT+9x8sfZcWMXEHgN19747U8L0o
|
||||
1SoiLoZNp8ZvKpLjteyc4mzme+yuCZWlRTMB3unR3Fxza0mh3CGQfga04/iLg/1c
|
||||
GvGeBCtZDSO7ffcQ8XrAtaLuqRXIYQ0J+y+S0wCgpiAz5diH1RB7v8dfQaIKeTcT
|
||||
FWcD/ivIHF3IGKGPTaLqzy8B7maVOvC/zm6Ci5IH3lcRfwY9+9pYhb9OlRZDpruj
|
||||
xjNT+Qg9rtjMRNhfx78VWvZl3fccB94tQ2nc5LQ28RtgmUYN9bv9fuotW/WjlYKM
|
||||
IdSErwMJ/0DH1vjPsJtEem3FIThTv00II6xdCw5tXbyqUawVA/4ghoKHt1OoAPD+
|
||||
cGZ+5fF6k8pdLpd2LS2jv0t9C2v5NS0k4RUYhuqpAGyARIWJPmpHRbuqE6eXjtMh
|
||||
DI9Ce39X33hDDIAa0iC0zmpgVFbvSDUWTINFfns/NMy5TYGNUjqYeRpSQtou6NtF
|
||||
eJAWbwhcnit/b3samkq5KC81yvtGarQrUXVlYmVjIFRlc3QgKGRlbW8ga2V5KSA8
|
||||
cXVlYmVjQGV4YW1wbGUubmV0PohdBBMRAgAVBQI246zRAwsKAwMVAwIDFgIBAheA
|
||||
ABIJEBxn7BM8ZhyEB2VHUEcAAQHRuACffM0sr0N0bfmPgFX2sMhKKLBRuSsAoJjM
|
||||
o+EWIUZVylgjzkQcQHwjmDLVuQENBDbjrOQQBACRouE/462OQbUUzNKbAJ3kMrc8
|
||||
xYB+Pi4oFFwAG9EAwDpMhjX1h63xySEuwNzXPaTFgHTo1oEim2Mq862tEkO+f0pC
|
||||
Ofv0uXr9haZIvh2KO3DYFV52wiayGO5OAwDLp6jyfSQlF3PPFsRryleW+OYbagj5
|
||||
1dj4KvgBCCg+Whny4wADBQP/fjurbVG3mNm0B0XU4ZeB1MUMOJYGDe7LYBmbGxwn
|
||||
NMupZ9Rxfb5ROE5ehyPzUf/DmrkK17fPfPHYdN/UDWbDnQHkVk5OD4Erl6ulQxuV
|
||||
jcOgfW70Tyl3ucnlZjTZeihEgczHKvO5ADWVmevLyidiYocTx0QMn8cBq9iSpFRd
|
||||
EvmITgQYEQIABgUCNuOs5AASCRAcZ+wTPGYchAdlR1BHAAEBiJcAoJTy/pFHvd9y
|
||||
xAYZBYp7qLG2lUIOAJ9Rlpbjou3wb81vE+Qev1+GQGpaVZkBogQ24644EQQAlNDo
|
||||
1aAt9iof3VI1z3TehyLrBIR4XmKRSM2Bx02CZhQRIwY/QsK6WBoxlJqfgUtsBUuf
|
||||
cztjJaUBixq5qPmBgXYqN9/B8HZvG2nknHdiqKrvqFpAqATJtlccW0tzPJKtKaTb
|
||||
tkORBDv6hssFa1aXwTN7IjN5nLI1Wh8lsvk9SKsAoP5Z4IDSK/mM9h6FPRsAsAYv
|
||||
d99ZA/40UwQLl06u7wBtmxqSdF/86kjC0kWX8J2Y9vIceiNEiE9MmVNcYIKwIM0m
|
||||
wduF50EksVjEdgWUJrqT3RztJfMT5+Sgm2KOAvvfmbKa8RF4NPSrVXDDrFeqk6uN
|
||||
DT0jnUUTQFYTjk4Pxg9Kl+a/c7Qee6qXn5qeDX8ubZqN0noX0QP/Y5HSgi62UbBP
|
||||
5B+e5BqE+ZLeJ7yVtl909NwTCr7KVZt1o3Za0dCYtMosPT9ObAjCanhSnuEWa3hu
|
||||
outOgorWaUSEW6Y3zBKvN/M4FA7+1Rhe86gnnWLt+rHqX5M8Y/7JTcrugNtR04DF
|
||||
sYga5A16CLsTDxSmM2Rgvpwh14FtrqG0KVJvbWVvIFRlc3QgKGRlbW8ga2V5KSA8
|
||||
cm9tZW9AZXhhbXBsZS5uZXQ+iF0EExECABUFAjbjrjgDCwoDAxUDAgMWAgECF4AA
|
||||
EgkQO9vtsXd/vtMHZUdQRwABAavgAKCWUwgFviV4MrPrUtCIDhMZZCn35ACfSAXu
|
||||
uu9e0d0Rz2QVDGB8BJkfhFm5AQ0ENuOuZhAEAInmt6zi1dFmPfqzs/gplZR/RgLy
|
||||
a0vHF40Rd7lyQC2fyAx9xJAngx6Lg7UQG+spn0PPbwSa/QWYN3roNR3jJtEiTU83
|
||||
yRavL1S4YsB/9UECQwjJeFgIScHvBGw2PiQXkOFiLK16nbB6Q+hxk7YYBSgjJjbI
|
||||
w1vabaDYrxScrZAHAAMFA/4jGKHej776LTZfCLjA57tqujbFJ4GYf1vycRony/xF
|
||||
UtE7QCChHgYvMp5M5+/nsVTjy2VjuzG2HoU7F4lpCRLWcPUtGlvcZQNmvuoz/I4Z
|
||||
inRaF1GAZb5zR5hrfaDlqOrbOff4fUvjKuZFJkzieZnlld72KOQazRQ1iqaLSAFj
|
||||
GohOBBgRAgAGBQI2465mABIJEDvb7bF3f77TB2VHUEcAAQFJ0QCgl+n9/5lZxK3l
|
||||
goKK1HWYfIYNSxIAoOxVFgrZ9x1jsIDsMcSszrP60JvgmQGiBDbjrwQRBADFLZOA
|
||||
CYlz942iqSIW4twe90tkmeu6yswZInI3pacFpOi53bAq2y7CFrA3/HzbYodK/QLP
|
||||
tmq3wKZDZcLghqtWZTxhhhH9fDqj8Rb54IVRGw3XKLD+GyJt5OhtrIBWzJevMQBp
|
||||
07ZEuRn8+N7k7s5z83WZxmyIz9LgZj32ZOhluwCg4YuIbbsa92PrnfZcdW1jPSql
|
||||
LQMEAIkWB5utOUWVQZHc5X2MdSMIJ/5fAoatzLD63wTLJWqQZ6tWp9v5xED5riHX
|
||||
vQugCzdbdNwx6SqJ8dl4I2Fc/KYLcthVO7cUkpthBPve+XV6d6L+E3w9SsZLDpe+
|
||||
9DwM4sS3zYT1tauANnBK7hoDu+KhF9/3wGtSdJ0Sg4JgP5oGA/9k0mSgmhR6HNyB
|
||||
0J5MoJhs82TaVWVdvtZCAfGdoTaPVfNT2Kc5WFfEpRudWo1tRt3j3LYuyTiD+jKr
|
||||
jVG2EeEzs2ctQ6uPlaqmQgenzniCi+NCCigKDDA2BTS6fc3E/rOvug0zx9u3hNVh
|
||||
LfjUIwYK9qHwv+IgFP55gGJqOMZ+2LQrU2llcnJhIFRlc3QgKGRlbW8ga2V5KSA8
|
||||
c2llcnJhQGV4YW1wbGUubmV0PohdBBMRAgAVBQI2468EAwsKAwMVAwIDFgIBAheA
|
||||
ABIJEKXmf3+jrj6hB2VHUEcAAQGvfwCgoevUn2afCdW1bLwbcRs5kYrM1GwAn04Y
|
||||
4r15A7ytYdO2PaxSkSJ4gn5NuQENBDbjr4AQBAC4cckdPiWgQNkGvAm3q8FxzRLo
|
||||
g68/jffvj8Mvt++XQ4NikO0VJ8ezYkVd+vG3v5RoHTISynmMWZZjT56aFDSDZPOk
|
||||
Qs2G0qZgAEgTpzCUBdlnUC8ZrHSTSQjCn7HtR2cpYCCUBliPtatDvS3Me1XdRfBh
|
||||
Xib04TB0ci6DrzFQkwADBQQAje0R1INm9GkZKAzTECi+lVei7wbXkn4JF6n9r1KL
|
||||
5oULVF8aGHNEJ1Twj7kuq2kacYjc/Di4KdESRTZN9szlZnNruvAd9JKHIgbeysen
|
||||
e3yRhy+YFaqXm1MtWCdwwaDiDoHDASpl55RtuCKxz6uW77qhrZ8E6GRDrhI92R88
|
||||
DbmITgQYEQIABgUCNuOvgAASCRCl5n9/o64+oQdlR1BHAAEBawkAnReKOagNQ/Ui
|
||||
7qWGxKWYY6I07+XhAJ9/kbrDpWSrx3zoS/YjBL1Z/i42ZpkBogQ247AKEQQAkOFN
|
||||
8GmHkbnVqUQNRoh8W8PQr6hcNeoMHuEODey1UillH313Zuj90865VaivBcUEMl4r
|
||||
RzuIkRCsxYqXF2ptEaQfyloVKcvldajjEyOSeqcnNi7eBvvfiKgUdMLhYMzb++hM
|
||||
a4WkvD56Ktb7CXXbC6wemc2RbEwQha3YegZN6t8AoPclQGtp49vyAcqdcXPIS7xE
|
||||
unezA/9doAqN740Bh6qFwCrG/ZIQ9SPwQyC1ftIOSTIO/zC5F9w3AwC3hfAdiecz
|
||||
dulTBaPYlwMYT2uw2dr8e4UCPP/aWuFQqdwfQLLC+OFi23W33aPRw9lp5HeljxH9
|
||||
ubw2zbS2I/u7FWWP6zMjY9/kqJQeGJYcnZFNcYTalSZPpQWFzQP+O7Jm8g0rCRtR
|
||||
JLCkq+yiLXl3p7hbHk9naYCtPnL5QuK0HHhYoixdXpRVVoQE1oF7reT1wUZ08Rtr
|
||||
8d+VJ3vqQuZxJ3L4Wvvd3dMwiubAAoxV0qNEARzeXztho93b8t1P5NbMJDDfcSi1
|
||||
7EnvJnNkDZInHbv+PIiBeRa3C+flQIy0KVRhbmdvIFRlc3QgKGRlbW8ga2V5KSA8
|
||||
dGFuZ29AZXhhbXBsZS5uZXQ+iF0EExECABUFAjbjsAoDCwoDAxUDAgMWAgECF4AA
|
||||
EgkQWMuaTIWoHzgHZUdQRwABASTiAJ4vnNwg4QN5Nj6dgloAUhXLEwOfQgCeIMtf
|
||||
rfz8JP9PectU+oN68EWxNM25AQ0ENuOwnhAEAJ69MNjnL5VF+xPLtgvHSRiI+8EV
|
||||
Oag2s8YdLcOef8myd/ysoQhX7K9nWdhO2cOmL3Nbt1k03/Npx+EvvyCRUiPqgYt0
|
||||
63MFbbfF2tz6O3CMzb0tGwYan5jjlyXOIoVJQA0dibpJv0Avn+mzvCGQQ1q/+y50
|
||||
+EsBD4T6GTTBW+t7AAMGBACdpIj93tczPsxKNoto5Dp8tSIMp9LEYrsNDl0PQeue
|
||||
s6dNhuarQzfiF4YC3X0KoKslnJD+ASwyeDbUKBDPzK9v+6I94dNV6W1POkdUBUDl
|
||||
5qFsN6u8qhFiMHzgagpUhdANeLF3Y0MGncmm0xbFuJvGZ+Yy1vtbB+D61Yx6DRM+
|
||||
AohOBBgRAgAGBQI247CeABIJEFjLmkyFqB84B2VHUEcAAQEImwCfYJ4NGyH/snAB
|
||||
xoxryuVciL3Cyu8AoMtIZ222A8al4XK0DrQqJAnIZlF+mQGiBDbjsakRBADettZo
|
||||
8gTOTr1nJXbk5sJfuVSQaMmbgLpZpMs3Q7C+gAX0XX+Q/vcuHp+wV2Nq0S4v+w5K
|
||||
+sxDF4A8UDf+q+GmNKMA5U27hkcDQvE48EYUghcdWKjWeFwmmJOb0KMoatdeh4iP
|
||||
T4j8ocGw+i0z6o/e0y0OVWsUvIqp4iZP3UlnOwCggOq5GfPJMq3K3cND3nU7GOR8
|
||||
e1EEAMcgH09o68Hbjbwpw+ejPuKwVFa37COX/65FF8PONeleq7Mr3Y8yKqbLIsIW
|
||||
DaxrlflpbyMz/ShuDdNU8gh+msfwh0+RNzdEPmpJCCVJOdZO46cudgbyAQriH7Py
|
||||
sSbi7AbmpnMl7kQruhAZWXLtnH1e1kKovB43a3ph8wF4kotyA/45A8bLKEmJvpq/
|
||||
amY6VjDnGsxkDjjw2OoVbt8sLdGjpganj3fvy5KRhWeWLKhmtq44tH97m4YDmGCH
|
||||
Va/Iic4aDPMMvUPWdaY5DyCeerVOb3JN1qLC7o5x2HBt8RE7cXnPJl5VKxc4qzys
|
||||
5bqQEYYt2dP4cJqKk3OjjCbl6TJ+8bQtVW5pZm9ybSBUZXN0IChkZW1vIGtleSkg
|
||||
PHVuaWZvcm1AZXhhbXBsZS5uZXQ+iF0EExECABUFAjbjsakDCwoDAxUDAgMWAgEC
|
||||
F4AAEgkQqUwPdWUyRNYHZUdQRwABATNbAJ4zGxw32J0seAfYM/ZTq0/S01HRPQCf
|
||||
eV8WCJ077Pxl4dfO44z1MBL6PPq5AQ0ENuOxwxAEALW77T00/jp0+efpEm1zMvcs
|
||||
SujKtw+Yc6TcVuI18nxgycUF5JP5T75yGL+QrOb43jLxNkTywfAaqeR4gG0lfZiZ
|
||||
AkWEqLZFH0C1WfYdXVlMFhPWr8/syllM8wj0Q4OUIQ8lO9f4x20/zGHQayPWLXC6
|
||||
NA4kCJd2uqw/F6fhJyHnAAMFA/41FE7MsWriQFSmChPK9bMmX3oZ3KR/47QCFtOV
|
||||
nuLH0q1At/EaurOCjSHAONvZDN5Yd+NWFpppJzlRY0y4hDIdFyyP3HifblcYTQdT
|
||||
I5VIPjog4CN9kX5t5c5r81thxH7PM5F9evWrJbaDihXws3izi5Xh09qZDeX3wuSD
|
||||
yWFYJ4hOBBgRAgAGBQI247HDABIJEKlMD3VlMkTWB2VHUEcAAQHOmACfWYGI6kN6
|
||||
0nJgsIXNyIc7dgEwDW8AnRblYLw9mIfJbLolrMCwxazbA5OVmQGiBDbjs5oRBACj
|
||||
AxqGzA6j190iiN/1vJvS5jYLQ1H3xxhzXdZ6ZxjPJkslX1oxFqBINhjzBJnV9/7b
|
||||
1FFe5089NiCcGUVZa2xD3Vu+niLTAGNTQeNy6Y0E6wEfvplQLJbpVGOmuVeZyShH
|
||||
NCKjrsZFtS1mr7o19SUb5QWS3gZHabFTbmhibcFBXwCg36qGVAnGcZzvnUTGpRy3
|
||||
xjp+zuED/2qTJNpnPhicKSksVwb6EJFXH7mQSZlyblAnOAVFMx19GUijW4MWP5FU
|
||||
dcTd5KzIDgkenRLBrpCLIFVkQ4/baP/hOiCLOmCoRu3xnFyoRPM/Jn94Qy3Jo2wi
|
||||
gwkhQU+zyOU5C85QBD9ctkbYp/0mu9bpxmYTchHwD1v3dXUXEVajA/9lnEz1GiI0
|
||||
bwKpm8VKXp0YYP5hea8Jh5fNVb1QW2QqGd+XNHnRGSqX5smGyrs+xoYxD8+jv1Fh
|
||||
mGaSv+6+n+JBVK4TuWrQpZ0cgZL5jZnX27TOYXeY4d5YKgE+7ZO57TwCIfF/P6pu
|
||||
flGm+t5GcFwj4kkfohMEaeNhm1S+xf29q7QrVmljdG9yIFRlc3QgKGRlbW8ga2V5
|
||||
KSA8dmljdG9yQGV4YW1wbGUub3JnPohdBBMRAgAVBQI247OaAwsKAwMVAwIDFgIB
|
||||
AheAABIJEEevS2lh8EeEB2VHUEcAAQHMSQCgwD4p9j1sDwR1+9bBrzNQzVIyzmsA
|
||||
oNL7pfcdW4Jou1XHNc6hv4MpsHtvuQENBDbjs74QBACHkUCB29pMkveMEZyNiKIm
|
||||
izF5NZ/cv91Rj319k3xHf0NJWhQp/1G38SxLkPLBdWcoB4mJRNjDyVsxFUXvRWFI
|
||||
MekwL0q1sHSWTcJwCpQs+LKKtPmD3LA3bhbuTSdpYgmKy21SH4epubqBzk/P0193
|
||||
mWXzHgSGLeUoTo3N7eBQ0wADBQP8C1Q3WGrBZNOmFVly0erclpQRv1qCa785yx/b
|
||||
j9ur2LxHwVozAEXh8jmoiKZyoAz7YFnp29kR2qtVplH1oePNyFweZqIjtmZbiCaT
|
||||
4scUVZ/3LuYbxgMoUFeRoG4mnEVvUUh8mmZovMmZFrvp0uojcDsfYTx0VBr8waxg
|
||||
Jrg2YguITQQYEQIABgUCNuOzvgASCRBHr0tpYfBHhAdlR1BHAAEBU90AoJzJUQIh
|
||||
rby+ZQ+BnaORdChD+c2RAJQOkYvVpmfV4qsOUdwbIPgLPLCemQGiBDbjtDQRBAC9
|
||||
Vf1MkTKc8kSxfdfZ8Y88OJAr6gHsPUg0j1t8gPk0q2ijyrJuK84ujzmLmbtFSITK
|
||||
FfcT2VSD1u4qa0iFqzSwnywtRGYKd0gq1eMhaDcp3SmaMTyrbPJ3sKFDd98nbTzv
|
||||
nA1tHgZCFI7VZO7HBGgvnd+370lNQsnGRBF/vUDObwCgllBimEp4tasu0WNvZYpt
|
||||
jGy3ni0EAJLsL9W7jR64h6+nZNkdO1jRT45sW8mvyMOt1BkyRQVK6G2Lut879t/u
|
||||
pPCYK+/ohWaf3TkAKH1ucrBm9xHlPXJHZvoIA3brt/OuJmG7r8Ub70N2vrZmdXas
|
||||
/w5ru7EBcKeii9pp8pi6mim8dXTPS1R/b7BqytB0dlO9zSl9j7noA/9Y5UnQobM/
|
||||
qT1tiNhJEnUwlvvTB1UWId2UiUR3k/eNCxc7IdUytanqofXSxAu2jyDB5Ymv1od6
|
||||
bRCNM1JNWnOnqVoEd/u2csTAIkZ5fl/kE6HztqRGPB+H0n3Nb4MGu2mpLq+OUNhT
|
||||
nLpEZsZGXqd21eFXkWkThxstrH+kYVYSrbQrV2hpc2t5IFRlc3QgKGRlbW8ga2V5
|
||||
KSA8d2hpc2t5QGV4YW1wbGUubmV0PohdBBMRAgAVBQI247Q0AwsKAwMVAwIDFgIB
|
||||
AheAABIJEN7w97jsZ9veB2VHUEcAAQGiagCfTG5biKrPKo3dZTpI+fMQuSuPNmwA
|
||||
oI3mCWnR+UrV5myTBsNmQ9vcnr8zuQENBDbjtFYQBADPV+xDMQ8NzkqoJyO+lriA
|
||||
UrCNIBf1Kbc6U/IPAGOoED1YVPX4EB27u3K/EmRVd3clFS085Dau5rFIr3d/xXnL
|
||||
n++wqSgQq0Jc7LflMpIj0P209/oKt6MBovTAQn3lNpecmWd8oxiKoPP158Zgm7iL
|
||||
cOvRTcs+/p0KAzNvHIvQdwADBQP8CQS48V16lhWOSXV6u3JOukMeWBw6Tx+7M1Cq
|
||||
yBihmR8ZNlF6FPBvVkX0NFVUH2qJn5yr6PmxQxSRnC3yCEyPBa48xqIditzynMbE
|
||||
IkNUrFZTE915rr0k9MrwzPGuLfaPtr/Miy4BI0dnZ/5U4hoxPwDbp0aPUwRqb8+T
|
||||
9POTZs6ITgQYEQIABgUCNuO0VgASCRDe8Pe47Gfb3gdlR1BHAAEB/yAAn18Lg2NX
|
||||
AdY6HW0LEurh0Xcv8zlWAJ9ePiLMYxpoW5nv4g4nuOAWoL/KLJkBogQ247TcEQQA
|
||||
rUqUbiVTMxJhp8bA4vMXAzCuLjys4A44DE+uRFb9AGsZTmw/FTPETO7iU/3frlyY
|
||||
yTgIvI2zDF1SwHXG06KF3yIu8LF6OCM0N0k7KnKpw8M2tkPiT+D8ANrHU5d178ev
|
||||
zm40PyNDyKxSGNlIG1N4MIKFtNdMlahLvu91kG04WesAoLPa5zISvsX+Ew95M1o4
|
||||
Qti8iYHbA/4wr+eYRywP35eb/F5V9bOLWhWmEDzw4KHXQ7V+OJ7JD5n44S5KLPKw
|
||||
IogohDlPmrxDTAJ/YAukApUItd30kr0Uq34QgFktAsqgCP7C5KEM1TTxU25Tcs4o
|
||||
jUHoDyMj14ECuiTCP0ZFRKUivopgjgRhFTKXVVWTySkQ0g9SDaITSgP/a0FyXMQU
|
||||
YJjuB7GA6r4U6QnIHsxS5xrQgkshb4tp2MVWMhqlhsfOLaj1WZ+oe0DxKw0O3YKT
|
||||
H/EAzmNelKcMbtTcilLaIdI5l+Ylam/bZe7QvbN2s72Kn2PZjtYqO3Uzqw14bqAJ
|
||||
Rl0ekleMdZRMMzAsour+iNVPHnlodXnQ2gy0J1hSYXkgVGVzdCAoZGVtbyBrZXkp
|
||||
IDx4cmF5QGV4YW1wbGUubmV0PohdBBMRAgAVBQI247TcAwsKAwMVAwIDFgIBAheA
|
||||
ABIJEIl5psVWf7NKB2VHUEcAAQG3TwCfQ9GqGIzMX4vfsPK9xpWX7TNKuZsAnR8v
|
||||
7wPkWtynWbdi0Eymj6Pl2yJ4uQENBDbjtQUQBADG4aUG+qgOTGEgOAVnN0ck76An
|
||||
Kb3jOBIYeQGYEgF/lDYbY7fOQ3tIgQ0jXrKD1zHLvORNsG708yDNR79S5Ci/1nph
|
||||
crNOPWMujOsZ2WMo5xblhG+WJujt4pcNSRK9P5fonUE4hV7GXTljg1yZ/ui00Ot7
|
||||
b1B8ryAYE79t1B3svwAECwP9Hg2r8lBq/j/t3kRO4xl108DFXiQKdj7sXugmAcMo
|
||||
mF4nG3j2s219dLEFlSwn0/peGvjp8JFPfcMPU/xHJSaZLf90mXsf+pHcDWujHgVA
|
||||
9YC6ThYaGx9Je+VmcVYomELxNnMWKyOJePDU4ViIXhMCvGP0Pt39wcQoiLjeu15+
|
||||
l/6ITgQYEQIABgUCNuO1BQASCRCJeabFVn+zSgdlR1BHAAEB7JAAnihkYWPnxhbW
|
||||
i9SUMaB3Qz0SfsLvAJsEGrvruaT2XPVKwa9FFfqRj6WPnpkBogQ247VREQQA3VAG
|
||||
c4T+vuvVXcka4ETaLaLlL1xOiPIdJMWRWWQ60CZqWXDVpFBw6oG2AyfUZiHhLlmT
|
||||
Zssz8UhXLw/URsPSpiGbtpGWKiLs4OCqjslN0lHzcnGqxGWCZJixMgZa5DcWZJjw
|
||||
qdXEbDChgm4ULP/7+iKvIenTQNhFoCXr9MtdoHMAoLpNCmSKlTu1H5GlWmYTK9An
|
||||
dWrfA/47ip0VYgzIvUhI0iWcG95sNfshApzPL6zPgKBqACogs/5/DfRn9g07BcuM
|
||||
ihLJD0PLNPVnOXqQRaN4Da7jLuJA53XtLgpogxG08M6XUimTucfcovu29/bgjZIK
|
||||
A5c8KJ2lzXSJ9jZxSoy+O051f7yhXbUmYC1vdNr8GBk69QKy/wQAiHMfU3cbCfTT
|
||||
Mmig+zBHCkHjqzqr/zKtR8RT5AwSOIU2aUIiHdV08apCelBw8PbEf077TuWCq2Yy
|
||||
DZJmgWRYh5cdaMgdAd7ul1FS1yHPZYshcofWjgXUJHR4I8iPCs5OmdHo2HK3uU2O
|
||||
M36ZQGSpFA5WN1NEm9GtMSBoYKN2ERC0K1lhbmtlZSBUZXN0IChkZW1vIGtleSkg
|
||||
PHlhbmtlZUBleGFtcGxlLm5ldD6IXQQTEQIAFQUCNuO1UQMLCgMDFQMCAxYCAQIX
|
||||
gAASCRCe7zTNSxGyXwdlR1BHAAEBSQQAoJRRe9UHKHiX2iFczXq6nrvr0NhLAJ99
|
||||
W/I5b2/2QQ01we8i1mcSYPWj47kBDQQ247VnEAQAmuK5RcS0zTyXp6SjW2+WeQIp
|
||||
JnJDflL0+iBe//3SADv01qUmw3jWMAuxG+CcCApksl122V9npEHiLC4Q2A69roLR
|
||||
sbxKBPebustfadLJoVYqPsvjnrBlafe5GcrFPnKbE0wV6ZXx/Tp/eSDiQlid4lWz
|
||||
5J+z/mN7KhHANzoRAbsAAwYEAJO5fkCSdNwkisFXzeKslWxm9Yoe1TOouiSV11he
|
||||
x0j94Hpz5wGWEXF7z+FbDq+4V0UqGkKxaERsl6HMWNkImj57N/9h1C1YDfiKTimg
|
||||
5tZpKmehXtldpWGCNDZrE0RasrFCKENVhFMhpc4kAnx6rbA0+LhRvJkvkdxY7pKU
|
||||
//aZiE4EGBECAAYFAjbjtWcAEgkQnu80zUsRsl8HZUdQRwABAfRcAJ99+4jghLty
|
||||
CHQ82CGv/S/cv82GdwCgk3C62Y3uSS/2f+g+qQHLMvG9m3iZAaIENuO1yxEEAIEM
|
||||
k4Zf0L/HEJVk0/o4fPpwvm8zc+KZQCFX70cBVU9BWJOcUquRg9JDJF9bOM5TxE7V
|
||||
OnkIfPvjug5vqP0/vjIfW7LvzIWDhS6FcFaKeG4IoqrgghbAmQIoEWvVTx+7xrpj
|
||||
o1yOqIMDQqYZEmsw+Zd6deQmkUYcbvytS82L0gx/AKC6DM0guH/ddkJlT4FQ9h5c
|
||||
v6dQAQQAgNdmGPW8VceCL2WaKMoOMmhwQGhqY3+1pDLo7HVFEPoe18A9jlMRHWfv
|
||||
Gb2EzMT46/Ugqkf8TzvZGFrWq7W/t45rp5O41YXQ2+ZJH3nl+t5Gw25Hwk0hvpK0
|
||||
jYRH2nMFR+PKQL2mDbA94LvClAkgX1MX4lrUG8bYj6FrbEnvzoAD+wcRS8A6xznx
|
||||
hs+Vsg/KnYl0Qe9dNFPY0hJVG5MxCyDy9X32cxhHYJSHbvS4/LLbFloP+Rhwn3/W
|
||||
eBjsL2lts1ahXvQ+QQw7+qPrs4hWJZU/NSEh1RGitukaG5zegHNTE6CJqXshshI9
|
||||
Ei0OCDahmhjiGrJA3HwKPZlkDMOkza8KtCdadWx1IFRlc3QgKGRlbW8ga2V5KSA8
|
||||
enVsdUBleGFtcGxlLm5ldD6IXQQTEQIAFQUCNuO1ywMLCgMDFQMCAxYCAQIXgAAS
|
||||
CRBrxHeAVKzSRgdlR1BHAAEBQOsAniVMkc7hW7GdLkLpb6YDiEUy0yrHAKC3dyJ1
|
||||
RI9tKXk1EOW9jTopkl5ysbkBDQQ247XyEAQAzHzwwUKDM7+djJo2/EnWmCijc6g3
|
||||
fStaGNoXDEovi3B2oPiiRTsigX90qB5nFP7whDfi8k4JY2Eig5hH+MGdvni36hYE
|
||||
nQSadsZueYofvQh14N3V8fUmx4hiQiMXyWiLJzc91ZiRjww4wZWn/4Y5f+0mb0fj
|
||||
CaVSxTxo4+7joU8AAwUD/0oL9Gm3gl1XVV8BhJoXVdFQ6PN9yEEXUbtcrfkC51kT
|
||||
Bk2NaEGqbB+kC8GEmXwyZcW7AQN7X6ikraUUm3RjTU7CvkSHobBnXYt7FhqZURpu
|
||||
V7eSqZGP5nP7SxWmCTTKgIH1kHCpWRwaexKFjIIkYgyVFqtEx9cEQ6D2kXPh+Rna
|
||||
iE4EGBECAAYFAjbjtfIAEgkQa8R3gFSs0kYHZUdQRwABAX1jAKC5Gp5sHM9sWdZe
|
||||
M6qfu54F2OwMQACfTjYXfpMApAROPkjhhFNqH0d8x5GZAaIEO6cTzxEEAMnukcmm
|
||||
91KqYvahVQdYaI/Gv//n4YDWL7BHNdArU3MA0xjcmimynR67KIXdsKu/kEVcQJvH
|
||||
6rlyL2J+BvRopxHRmT+J4FKdQjzb0BdJMoKzxBd/v3ZwinW0fjlvTXabncnbRO3K
|
||||
fsD6Bd5FFv+0HOFfUJTQCga5YtNYrQZxIz5jAKDrTFXeC0ABRhQNBB/ym2jiJqzD
|
||||
RQP/ZK9t7tKX2GKmrdn8sFec3j9h1QNnDoP/82xrXZQRICNusMBEhPzD7OAEo0Vi
|
||||
gpz2Tu++wWci7ghKjCCMqmgYQDGJVmVbJgrqM+4WgPQv7jD2Q/yRUhlkf7/dp0SN
|
||||
FXfodHxOOD3d5Fj0zBMfprKle56vHjIDfpNwaz8k2XjZMw4D/i1v0WycSLrbSWcC
|
||||
YavqVEeZtkJ4UMHcjsjQz0VrI7T/DMmMeYoaqs8rzHlDJGuT2Nz4Q3kx8pY/lTLp
|
||||
k6n6aYq7HTvXHZSX5J0+An/7Vgj3UKH8Ks7/N/dN57ZJY55+6llmQkpg/PV0cdQN
|
||||
DSbKeVYkeA4tJrDjViGje86h6ZTUtCJIYXJyeSBILiAodGVzdCBrZXkpIDxoaEBA
|
||||
ZGRvcmYuZGU+iGAEExECACAFAjunE88FCQABUYAFCwcKAwQDFQMCAxYCAQIeAQIX
|
||||
gAAKCRB/8jC/nVY+ViD9AJsHf9byAEuDOECER69NAm18N2WdpACcDiaOaA3gd01M
|
||||
kdEz54toKFIpPEa5AQ0EO6cT2BAEAO3Onn+URLuPNsFVz6rrIWenJbpzGYTdNf7n
|
||||
9kAFIXfFAKL8nPtdne4zL6UQcHAABDOAd4gCI9tQSPHTrX1tSlzDF2xJL5sbFFxk
|
||||
aN1ivB9oh4+ToMXEGNOHAZ9SRinFqdBotzr84zg/rGVFTzhSuMkPCMUu+1NCKGJ4
|
||||
B6wIJ6/LAAMFA/0e7Jom6d9wPQ+LZDRBK7cH/yG+Ylq5ixl86AL3ERZL/JUuUe4B
|
||||
2iVPx331sY4G5pDC3sqv8FcmItditfFO8FYJFMWD2DfTdbtGU4XRwgd6BQ3192Aa
|
||||
LcwyjzpuEMrplCFQjTV0OfEFogRchP4x5UGx6gdyXRDi5n73CqQlGS4er4hMBBgR
|
||||
AgAMBQI7pxPYBQkAAVGAAAoJEH/yML+dVj5WO4MAnRC1ThcLd+ucK3uM0OvaqL4I
|
||||
B14GAJwNvBDmPEOrXuES/xFiuDa5aRzbyJiLBDunE9kBA/9nslf97u62S2MfyPtD
|
||||
taRtydoB9/s8KQlYakcTWajVSeoKXqSyyBNmWL1Elkx0q0mm9OoEvFRLjVBHPn4x
|
||||
CO2M5vZQgnxU8SJcHrVsJnFYu1fSQsa+LRHqToiX3LY7vKaKJ/5o9gTYWpbsX/ZD
|
||||
kS6UxuRa1BRoFYZdCS8A2/QSGQAFEbQmSGFycnkgQS4gKFJTQSB0ZXN0IGtleSkg
|
||||
PGhoQEBkZG9yZi5kZT6IuQQTAQEAIwUCO6cT2QIbDwUJAAKjAAULBwoDBAMVAwID
|
||||
FgIBAh4BAheAAAoJEJ6cEKDO2FT/Ad8D/09Z93LR+W85FFzr+zvPhkp0oJ9MVcnu
|
||||
OceEzNhT7uPyaf9ZYtgyHdjMnRMMPqZZnP8fwoyrkSoB/vDy/M9t9H2RHGbdU0El
|
||||
FRdqSWwMkGWzpA1cxMw5QuqznHLrHj6VsOkQ2jpGmY3yBQwJBbF19eGq3V5jJLW0
|
||||
Lzyn9HM37ToRmQGhBDuoot4RBADa7tyCsjFl/2zvNQr/r+GH/aCf12wlxsmVE1cs
|
||||
/GdkO4nvZgzB0m5RKPfsTEf18Op4wZh6y4rQJHCUFxVkG7MbPD2d/aUay1nU7vCo
|
||||
t6vG89vkUMtuebZY3tXNQfwVrt8lo87DnB/GA0dKPS0SQzbf08Hhahw4EUQDEWI3
|
||||
uvf/4wCgombN0n8cpUVPaoDMZkyJWXOd858D+wYzmkIbHk951dsM1wOLQv7athDw
|
||||
D7YHi/s34V1rWoZVmuT2U3EZiLusYJ5c/bgsRu9+A3Y6rDmh3XL5d9gpp2JEsWgJ
|
||||
MI4U79/AtyzjiwgO3hw3QuWooh+VB117qM8Sw9XyFhlmSD0ojxgtnrh2YW4Ow/YB
|
||||
9yU4iLvwP4iaCuH8A/dIqE8xObbkAi3NbyDewi6LTYSnLQkHvUQhBuMBJUfBLHKN
|
||||
vd28/Y5udS44qQvz8oEQ1zAmo0/y+kHWxfxh3eFHQiML4MS35srPBisCXOpJGoJ0
|
||||
dJ8c4y9a9srzeg6ZJGbTwoFQQZbaAIxcciRus7NvnCOEpyKJEba0lxhyVTCftCJI
|
||||
YXJyeSBILiAodGVzdCBrZXkpIDxoaEBAZGRvcmYuZGU+iGAEExECACAFAjuoot4F
|
||||
CQABUYAFCwcKAwQDFQMCAxYCAQIeAQIXgAAKCRBCNzY0Y/tTEbmxAJ49YOdvcxh7
|
||||
tCPAVPcLWExYS+BesgCfQQhQ1qWjKuLy9yWDfGKS+5Qlsqm5AQ0EO6ii6BAEAKHp
|
||||
h48Yh6jezPm1Tb2F9UOfgLAEKHXbwv5F3nznYc3/cjCHLXJNISqlq+ZflRMu8lpU
|
||||
Wf2HQLzVFYXtDWoBrujlOldYy1IWKOvvYPBRIVrbe6r4tnklRN/2DY8DVWSSFovt
|
||||
NhWtyUGbil+wDAQoDbWQXhjnfr4zOv+gJIjMYbzXAAMFA/93V+ufNG4jqm6OrcMw
|
||||
f6E1GH0pBlySOwu1O6QrLXx/YlK+cMQqPyy/oZ6Uj8MqUFIJEBbQwe7byubHlYKb
|
||||
JG6bs4ecOUggATX3Bnby7HwB/xjQI6ECphjxmrGqtvbewG8LGSZNhmfrx44L0gLo
|
||||
8bp77j8pAaCc1syS8HNue/3K1IhLBBgRAgAMBQI7qKLoBQkAAVGAAAoJEEI3NjRj
|
||||
+1MRb1kAnRcw4bpKaM7wyUoOK4rJuas+gOfMAJYsoMCmvozGAeeTJE7k8AWm9pLZ
|
||||
mIsEO6ii6QED/2vr03VB1JAzjQhzifY2ueHye0X/BcjtSFWhN6jIQzHHnRH8oSaN
|
||||
Mp0d42gvxNp5aypEs72SFO4W580DsxbNdtSJhaC6hnpncAg8yAsZIo3Ix7v738Yk
|
||||
h4zOB/4RLwmZJzm2gG+soiQAATTOBvnD0IJumU06pCRUHQDJ0daHswrRAAURtCZI
|
||||
YXJyeSBBLiAoUlNBIHRlc3Qga2V5KSA8aGhAQGRkb3JmLmRlPoi5BBMBAQAjBQI7
|
||||
qKLpAhsPBQkAAqMABQsHCgMEAxUDAgMWAgECHgECF4AACgkQg6m004p3Kwg6xAP/
|
||||
VgizRHS+2Rxh/kVKI1/PRQpVGCEl9uHB58peMdPl3aAXxBcOoO+74cfb3ce+rD0D
|
||||
EGhjXKcXDl2dwLl/lSAOdUwHPdLi6Miv4IvoMyMsCyxFIgGnr7qZUFOzEues9H0I
|
||||
bVbwSv6pJMCgyc0aOnRyCFfT3m9lXL9hIIUVvawatnqZAaIEO7NiKhEEAMlPZPLF
|
||||
VnBUnc9J2lZRdVmnHWgYCRc2kYgfeLMqY7Q9l/Nd1SxuCt8DpudwVs/8w+6oNIH+
|
||||
iH1k4qcZYOt7afw5C5Vn8LEN9NfcTTkvwEqb9z8FNeKTAqGK8lpl25NgANwqtxql
|
||||
gK9bZUuxzNIizsc/GqgkjwL5TgI6vpicdFoXAKDWyCdU8Q3EK6xoFWxPR5D98VqG
|
||||
pwP9FdCrFqC/Nt3rJHAq9PNCWJWtTO/TiK8LS8Pym7YRobKLzGAA41uBaEcUxhJA
|
||||
OJKeW8m4jq9mfmQixGIoDWm1oBbM5ooTySUBweJZUh13IJmocOYE++KxI7RXGmru
|
||||
aFcCG0pusHLJoanyzh6KeUby9S/PtY9Bo3vc8I239EPhj08D/i9l+cdXCGhGwOWQ
|
||||
xsCOUcXLV8zbf+lL0Aw/bcwtr6+CSCsW+DdnRsJzcyKsKz/EezJE89LUsmFqZXnH
|
||||
aSdXQ+UdMAegZoY+hqlnIOxhkM2RlGqO2egcJ8TJrzeuHEHsYkiwQozyhInnXmQd
|
||||
htDnQ+PrtYgr0BY5niwwB6t8NCGOtCJIYXJyeSBILiAodGVzdCBrZXkpIDxoaEBA
|
||||
ZGRvcmYuZGU+iGAEExECACAFAjuzYioFCQABUYAFCwcKAwQDFQMCAxYCAQIeAQIX
|
||||
gAAKCRDIQJy3y8q66ZRzAJwM2w8QpKAMfZsOIPKOiJKICCXlYwCfYKaaJ5LOz6mq
|
||||
kSbVgDVtpeAZJJWwAgAAuQENBDuzYjUQBACJygT7QnMtfDnFUnixXdXu/vOCqTbX
|
||||
vmysKnnI4OeDW9QxTr+ugf+f6ROykJFF75zq/53jgDD2cQkUjU2OWbrrqWF/aYHp
|
||||
YM21TDtIRfRe0llF1kSHPnYW2rjnY4/AeWvPjToevxursEn1J3Ijd6NentxE/FWh
|
||||
etTEHSWE784/NwAECwP/fpxILkyJUfPdNY5HqN4Aag1g0ZWjVfaWrebZDt0BIHJp
|
||||
Qd8RvUtQnOzCOZ29KOQKS9LHOJOB2EjysCKTwBDYK5ZonQUtmhdwNZeoLYlLrH1P
|
||||
Q9WuhddjT6dJWMl2yJ+zchmDRFajf+4AvrbYGnMbMdjCllnDcygSlzUt7KGcjuuI
|
||||
TAQYEQIADAUCO7NiNQUJAAFRgAAKCRDIQJy3y8q66b5jAJ9ROwHyPzvGq/vgztzs
|
||||
4972gMuDIQCfeQq3q4tW3qoWyC/TOkvTSeUuzwSwAgAAmIsEO7NiNwED/2S8L4RT
|
||||
6WxoBdOIu6eqS0McmZO7IDt9rDsXtpGG0CuXHajIgiSgEuYxX7uMHsNvbvV2JQyn
|
||||
P3ZyKhym5xYcjwt/pu2EpN09ZaTstXryDM2pWl0D2bSfkbjEa0DumA+aZpDXix5N
|
||||
juWsaQ1KZPFWerfJKrKCjRLe1ODBkvKlgAVpAAUTtCZIYXJyeSBBLiAoUlNBIHRl
|
||||
c3Qga2V5KSA8aGhAQGRkb3JmLmRlPoi5BBMBAQAjBQI7s2I3AhsPBQkAAqMABQsH
|
||||
CgMEAxUDAgMWAgECHgECF4AACgkQn5OQvjVwcDdcLwP+KHNNbeyiJbRnQ8lN12MM
|
||||
wPUn5mukWYb9zHnTNF8R5xFui9ZSIRzOOilw7DkbpoIlFz1Wwk9TfOQMtYD2U+Ts
|
||||
u/2a2jxDJuxS82ugY2LjsZpUY9HZ6x7v7xZpY64xpWD88zcqIrenMWTrG1pU/xr+
|
||||
mCQywk9dFARsoeRrZWH7fHKwAgAAmQGiBDu0KcsRBAD9+Zd8zw33dyY80G7qcBZD
|
||||
kw56//8J8ivxH2EZEfcVXxs7vnyAUuQdfZF/+5FzKjxkd4vDVwjRR/MLcDtMmvrY
|
||||
wCgsFLZ+f3CADN3sqyckVwqakpVCpRfQQ3SL6TiqenWPIwIs0BV1PBVe4xOkEoSB
|
||||
gAjnFc0roWeWYrhEBDjYzwCgpEMYeOKONrccun/7g/z+HAdh3xED/0aOuwx/L3HK
|
||||
dLaj32jsuQhoTiyQns5h4lV+5n0boXtDslEihN13g6ocx4i8sgyh2JPSmuapFR3A
|
||||
RBLpCLwdXACyJR00v2h2V5Y5vfzQW3pC6OfjOGy6/K3tLn9y1Tgk+k4KiSKH/YPS
|
||||
MfNIw7lE8EqrvBCORT8LddKbT2+xai7rA/9pJ0HoibbLjuqIb2YehSwIqX0Jolfp
|
||||
b6GXk+2j04tbpCRg+h8yzrWGbNcoRkSXoZuqG77WtR3/fnFqG+H6GCO1Gxbdcdx3
|
||||
tWsA/CQSu4WA4zTWr76xmD/glc8MtWEAdiLteKe8GwoC85e8waqGAHK/Iz1VLptw
|
||||
gXuSCQi9K6h1jLQiSGFycnkgSC4gKHRlc3Qga2V5KSA8aGhAQGRkb3JmLmRlPohg
|
||||
BBMRAgAgBQI7tCnLBQkAAVGABQsHCgMEAxUDAgMWAgECHgECF4AACgkQBAwmnIJS
|
||||
W2YqwgCgnm7EYwm08AAYQEWJ1PJtDjguT8AAn2mHZZSIkVNR41htlr1gdyDWCTb7
|
||||
sAIAALkBDQQ7tCnREAQAvkwf0DiD1zbcqiBajDGZhDvE0cb5BUbMcuJvSH0FBXop
|
||||
IIniYcmnfu5q393y8WPc/rVrJVHrAU2RyHTAoX8vI14Hvc4HUFDdnoj6Wk/xSiuY
|
||||
P8C4VN0NX3G+S+C4Pa1Er2s/m4X9PRz/YA0bMVynp7f9QM18aN++OpWV2jVBRd8A
|
||||
AwUD/3cuV7jHchUeZ7h6Upagzj7quky9o6o5lB///Pk9QZ5HEBQTCJDvmu13xCaa
|
||||
O9II4XFwjYntYbPOxOTJ1aEBKQubkUo0SIj8i5rhLTeDkkHB5M/rO40gS/MFNMVW
|
||||
qFCvUIQk7yBkum+MFcJFSEz7OMpL3K5X93W9twllqtUZqjvuiEwEGBECAAwFAju0
|
||||
KdEFCQABUYAACgkQBAwmnIJSW2YNEwCfbPwQzlrLRCUuJM2inVLcz/3jijIAoJWg
|
||||
gcMT69FfppDw3sA2h2PtAdOAsAIAAJiLBDu0KdIBBADLr2l43qiQ89pgGz1gEa8i
|
||||
JyrLvkiYjgbMjT3V9liCUwAXEYexXJD9OyKHXgzxRoeBIEvxRJQ2UbDJS+Uln+hY
|
||||
/NCVF7sq2yzZr79KlJQzVcNbiaHmLpSMqVNWW7hkqvrA1cmLqzw5F05QX6bTBiCO
|
||||
2LrvkOV5Nwl8prw7EDW7JQAFEbQmSGFycnkgQS4gKFJTQSB0ZXN0IGtleSkgPGho
|
||||
QEBkZG9yZi5kZT6IuQQTAQEAIwUCO7Qp0gIbDwUJAAKjAAULBwoDBAMVAwIDFgIB
|
||||
Ah4BAheAAAoJEJsH4rxTFNch1x0D/2WcB2ranNdpej5/YmsJlJha7vI5zoTCQMwk
|
||||
Px/oFJXZjfarEkFdKRY/nz+zZDVxDzr5DuA0vjBP5h3JuycQwuGdDGW7eF5ZIX34
|
||||
ntCepMLohLkqEO9JWUMWzBN3/pQXDSUyIbE7qSRLKqn9zGgvsrbx7vwnBPFJE/Qz
|
||||
0gREuUJ9sAIAAJkBogQ7tCz5EQQAtqJpy5L5ipND1euXjra9IDoCG+iGbo9Rbx2D
|
||||
eQw62EQxWfT5+JCLsy98OuDCznWB4qSU+gc/Acpmz39PuGKbZ1ysfM2y6Ht7yLqR
|
||||
UZJfIs8slQKeGSXPEOcEQSOddQbW5lDPfTov/AT2hf9vvpi3TyBuQ9rfeVh56nRv
|
||||
C87igEcAoJgCFriL+cHkx1XTdemk5462nlRvBACwLOfshZJfof2hgg2fJgEo6nUG
|
||||
meJ2axHzvy3NEd0zToDaUEaoX074m3sfu+WqiBfbgtG4TvLD1pRNYrGLD/pQ/5AQ
|
||||
ocBHdEBs+/1ODiurIwPAeHOR5uRzXtUnJVJosgQSjpNKQ6X60KoG9XVPmqr7PmUb
|
||||
NxpapFgKRcQm7djfaAQApjae7+WszMEIddG6c24xuFKRwhvw6mVtZzggN+vHDvjS
|
||||
IKyDnCHYY3OYS0/PDLdrLqxCGQau5XqlilSKLkyzbh7zO1KfznHua4uLUSF2qkTE
|
||||
q3njvBfPxKFdKE/YWy3ptV+xoZsVTlreRf/sEQzPNGtxJ3qDzloIZbFr9N3oXwO0
|
||||
IkhhcnJ5IEguICh0ZXN0IGtleSkgPGhoQEBkZG9yZi5kZT6IYAQTEQIAIAUCO7Qs
|
||||
+QUJAAFRgAULBwoDBAMVAwIDFgIBAh4BAheAAAoJEAzxRunkmECDz9MAn08okktW
|
||||
vgrAJ600zYVZH7Qt26D/AJ9uA9PUHta29AzO1Owmibj2xzWsaLACAAC5AQ0EO7Qt
|
||||
ABAEAM1AVhC7V3EnU5XF7M7OPozDnk9fOgGpCh4HeD8Emuqh4TRVWSmCSA+YqWt5
|
||||
r1L4TpV4QQX+vUDHet2i/IieIFKOrowuwiONln+YGToxXSB8tOKKr4p0qJ/w4ozi
|
||||
jJZ6NVBmsGeXZIpu5LB2Ar4K3z3HZmwNSlDznVNwXJXNpfIXAAMHA/48d7y3W9y7
|
||||
jHD6QatVl68EelxV/x7BWHQF0JEltwHCKN65H5yV6IhUn84VNJazS5jVwYUvbmbQ
|
||||
u09Ndm7iKX/Gfwo5EyPxGzbLl/W5fA3vn1USXJFX2Tk7wALQ5SAZHHbrluIp/660
|
||||
zvXn3E+466KchiRCdOfqFpCd3Rxgrv/hAohMBBgRAgAMBQI7tC0ABQkAAVGAAAoJ
|
||||
EAzxRunkmECDFXwAn0NXK//V3U3k1LNXeU0mz6GYmaPRAJ9eRstO6/n170QF3Q7b
|
||||
kGNUvtPVdbACAACYiwQ7tC0BAQP/d9zC0s9/3Arm1Wul0feKO5jPA0pk/iZdcCDQ
|
||||
WYqoMflu2d9j3vIqFNN/tq9JDlvUXtdc4119Pr5Mgh7pVnSaQtYqbih8fbYgNUbX
|
||||
1NrqqtgeI7n28S5W+SMfR/uLCpdGSRoch/gvmKz2u7pnyQL/Tcm5ffMP0gkgjNVG
|
||||
a0ok/1MABRG0JkhhcnJ5IEEuIChSU0EgdGVzdCBrZXkpIDxoaEBAZGRvcmYuZGU+
|
||||
iLkEEwEBACMFAju0LQECGw8FCQACowAFCwcKAwQDFQMCAxYCAQIeAQIXgAAKCRBq
|
||||
3kKidAP1iVhsA/9q+o0L8lqSELMitAcEe8q74t+gaoQgOzIdWZp0G4GYaxyHU6xU
|
||||
AuWt18WAOJdf1WG+vmlz5kVX4OvlTQFl0oeVEfCEvNTaOJsUlPEajB8o3RrKzhxr
|
||||
rJ+nJGZV7SYs7CbF2cfrnuLMZ3vc07YlGMAxZU5QDTT4sKZ0hkEBhGqylrACAACZ
|
||||
AaIEO7Qv2REEAPz8+IF8X/cOgaxp1lafMWamZoGa7JaLvAbtQJZV8JZ/2au1iAXn
|
||||
j/C5f7BS8fQk4uE94mQy6cj1TBkNCJEARCrGRUQ3cSMBrFD/7WKneU9OLuTbG6cv
|
||||
B6LRBZv+LauSi2+I7OD+1k4VhZrYyISGIzHStJAFQezNLe+Md9zlNVrvAKCT0YGS
|
||||
v2bgvlU4D4+f9Li+20NGMwP/UKayvNs6H4TxWJipMNQep1rDOUDKNTyIJWaPAzA7
|
||||
5l+iFuyrBAw3cN4NTsDKRdNCCOfmlrC21j0eSDcizy3jVeXAdkKszQSLKCsrbGq4
|
||||
yL+ZIgHlfQdL8smSMIl6C0X746Ez9VU95acjjjhvh8WTw12jkbIR1RL9HP8LX62+
|
||||
r/MD/1ixh16oBvtK0l8QOVrbm/H6FwTZspf5bLb5G0RRBX1VJbKH4GCzlLyQ34fA
|
||||
Wl1xen6Pf5beJP5CMnG2eWYCrS6AluUuIJgo1w+vx4MGvq9OMdKyJZcYLbWUnx7C
|
||||
DbOo/1m+vZsXikA8z+GFfRsOLwL+HSdSQVxEZbG6hWJ+jRMutCJIYXJyeSBILiAo
|
||||
dGVzdCBrZXkpIDxoaEBAZGRvcmYuZGU+iGAEExECACAFAju0L9kFCQABUYAFCwcK
|
||||
AwQDFQMCAxYCAQIeAQIXgAAKCRBwEnpBKosIQEDhAJ0cAahtG1+/4gMMWltbitSq
|
||||
bTNBrACdEUWzmwEVSOrX/nMbvhAejSljTtqwAgAAuQENBDu0L94QBADW/R4I4DMQ
|
||||
vkGlvP6jxWLz6TgkPMAAfEyxIJoZYLJggau4XJYyElmUGVFVH36DPE0453yN7j3g
|
||||
BxVbOCZamUOINyehuBy8Gxom36Oegzvr/43TcNPTHZnVl9wJVCFmOsAR3L8A617l
|
||||
AguvUzlj4e7GwV5yCwwlNtBGO27Lq/dISwADBgP+JB4l+2Bdx9wMs1zVDGQj0BER
|
||||
tyHmwSVzLn3BG0pAM9wf6Me5/o633rOOQYl1mwmXXjUWZasmjegqWLUFPEkCyFMH
|
||||
R0CWWI9CdBOQROBFb6jK9Oq2jYoGxTJ4kCtMGo3z/pNsAGdNtgj5s0AgUIoQHw+L
|
||||
7u6XF8De/Sww56eyuKOITAQYEQIADAUCO7Qv3gUJAAFRgAAKCRBwEnpBKosIQNT/
|
||||
AJ9z794Z40YOapyZWN3NyQPI1zM0vwCfZIkY3c9J7WVXDqO+FlXWrb9L722wAgAA
|
||||
mIsEO7Qv4AED/1NZpI/iOHgQiAqloxQaiXvOL9X5hbtXPbFMN8J1S+78cRxBKtcb
|
||||
z4HXz5V0OrTKXG7aXu521hrlOeeAjBFhf2SvfYmPi5/s6RtQlv26+mLUFgptXy8M
|
||||
NViaADZaFIpmbPQfaRbY1RjVg8kSPKt35cOa3DqO2gjNfgbTUITTOUQvAAUTtCZI
|
||||
YXJyeSBBLiAoUlNBIHRlc3Qga2V5KSA8aGhAQGRkb3JmLmRlPoi5BBMBAQAjBQI7
|
||||
tC/gAhsPBQkAAqMABQsHCgMEAxUDAgMWAgECHgECF4AACgkQR6zxLyoSmJnf1wP+
|
||||
Lianh9lizALW8bgEWU7A8K6H9WnVSqVYJ/yihZXv8iHeHKNA5nhUumvx2xz2FbZU
|
||||
Nk1lgElbuoHjaG7mt+jJxvbx7NluGJkBk0jvE9zFz+LDqfaIp8Lb3IGVvlxnwl+D
|
||||
wGQ6MR1MDf1FcBpIlMEY5UFV99b5D8WQ0dlAaB4wWA6wAgAA
|
||||
=Xw/z
|
||||
-----END PGP ARMORED FILE-----
|
@ -1,28 +0,0 @@
|
||||
This is a test pubring generated by pgp 5 beta
|
||||
|
||||
Type Bits KeyID Created Expires Algorithm Use
|
||||
sec+ 768 439F02CA 1998-03-17 ---------- DSS Sign and Encrypt
|
||||
sub 768 CB879DE9 1998-03-17 ---------- Diffie-Hellman
|
||||
uid pgp5 test <pgp5@dev.null>
|
||||
|
||||
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
Version: GNUPG v0.2.13a (Linux)
|
||||
Comment: This is an alpha version!
|
||||
Comment: Use "gpgm --dearmor" for unpacking
|
||||
|
||||
mQFCBDUOrE4RAwDbbxWAbWsheUJprK6VryMTpwDiYwMfL+92nrHqSfPqlpMWgDTia8qnpRSXbyEm
|
||||
Sppp/6/Ygp+N3n32Kznq7PjHXiuWLlZGvZMtzmvaMA17y0GY6oLBxS7rhASXIKa9hEUAoP+KBFly
|
||||
qNMdsK8j+ZO0A8rnImGrAwC1ddDme5iZFkTEWHhrtU97sEu2GDkSQB8HdX8CoRcrOz/B2WliF6qf
|
||||
BKhcZPFVBIhKNzjTfY7SEYAZk2zcsCm8elnwSLaGEzxKFNFBqKDNXP+a35spcqsHSGzDVw4VuKMD
|
||||
AJNnAP6skpHlhVAmecLZT9eRzVoOq1ivUIntK2Mh47qsL74q6BBwz2sviPU2Y3pDlbb6Ed0qJAXv
|
||||
dCT24hlfoGoXzkoDInkPJTJeL0gCnwmQPjvXFFd71Cvg5LaL4lIQLbABh7QZcGdwNSB0ZXN0IDxw
|
||||
Z3A1QGRldi5udWxsPrABA4kASwQQEQIACwUCNQ6sTgQLAwECAAoJENY0E25DnwLKxIoAoPSyM/Mw
|
||||
BogpyMU5YY+Sj74k3UIfAJ0RopQa8ciickDVzoSVPrGysrnOkLABZ7kAzQQ1DqxWEAMA/wVrlNsP
|
||||
qTxWZbUiMrUN8MjTFR2xUhuTw3cdvRgiVPUT/q1l1+I3CpopVBx/XuAkg5sHB80zc6pZg652YFV3
|
||||
dLoTceS7ridb5k23sHa2hZGCeTo6AdxIOy53giCPDP9FAAICAv9Oh5/OVxUqI+6hsp9ccOEhRA9N
|
||||
8aJzYDPjvCQyhgej2P1kTsBZqWIx0/PiMvIt+qqhT2YfyD68mHIBztScAXZKTnjroUPKl0+bkX09
|
||||
NbdyqojAkzhaCRKUzwnaHEfhi2WwAYeJAD8DBRg1DqxW1jQTbkOfAsoRAnaPAJ0Z/k6Y2ypgDhXo
|
||||
qBLeW7Lq/AKYEACeLTod6Nt117DkqDz9epmIqwWOE1ewAWc=
|
||||
=6BrN
|
||||
-----END PGP ARMORED FILE-----
|
@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
for i in $plain_files ; do
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --always-trust -seat \
|
||||
-r two -o x --yes $i
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
@ -1,737 +0,0 @@
|
||||
26 demo keys (passphrase is "abc"):
|
||||
|
||||
sec 1024D/68697734 1999-03-08 Alpha Test (demo key) <alpha@example.net>
|
||||
uid Alice (demo key)
|
||||
uid Alfa Test (demo key) <alfa@example.net>
|
||||
ssb 1024g/46A871F8 1999-03-08
|
||||
sec 1024D/1AFDAB6C 1999-03-08 Charlie Test (demo key) <charlie@example.net>
|
||||
ssb 1024g/BC43DA60 1999-03-08
|
||||
sec 1024D/FAEF6D1B 1999-03-08 Echo Test (demo key) <echo@example.net>
|
||||
uid Eve (demo key)
|
||||
uid Echelon (demo key)
|
||||
ssb 1024g/7272144D 1999-03-08
|
||||
sec 1024D/8FC282E6 1999-03-08 Golf Test (demo key) <golf@example.net>
|
||||
ssb 1024g/9DCAD354 1999-03-08
|
||||
sec 1024D/04259677 1999-03-08 India Test (demo key) <india@example.net>
|
||||
ssb 1024g/61F76C73 1999-03-08
|
||||
sec 1024D/43C2D0C7 1999-03-08 Kilo Test (demo key) <kilo@example.net>
|
||||
ssb 1024g/9AF64D02 1999-03-08
|
||||
sec 1024D/A9E3B0B2 1999-03-08 Bravo Test (demo key) <bravo@example.net>
|
||||
uid Bob (demo key)
|
||||
ssb 1024g/E29BA37F 1999-03-08
|
||||
sec 1024D/EB9DC9E6 1999-03-08 Delta Test (demo key) <delta@example.net>
|
||||
ssb 1024g/B0C45424 1999-03-08
|
||||
sec 1024D/7372E243 1999-03-08 Foxtrot Test (demo key) <foxtrot@example.net>
|
||||
ssb 1024g/EE45198E 1999-03-08
|
||||
sec 1024D/34C6E3F1 1999-03-08 Hotel Test (demo key) <hotel@example.net>
|
||||
ssb 1024g/D622AD0A 1999-03-08
|
||||
sec 1024D/D2699313 1999-03-08 Juliet Test (demo key) <juliet@example.net>
|
||||
ssb 1024g/35F8F136 1999-03-08
|
||||
sec 1024D/B79103F8 1999-03-08 Lima Test (demo key) <lima@example.net>
|
||||
ssb 1024g/FE56350C 1999-03-08
|
||||
sec 1024D/BE5CF886 1999-03-08 Mike Test (demo key) <mike@example.net>
|
||||
uid Mallory (demo key)
|
||||
ssb 1024g/4F31EAE8 1999-03-08
|
||||
sec 1024D/30CEC684 1999-03-08 November Test (demo key) <november@example.net>
|
||||
ssb 1024g/8B70E472 1999-03-08
|
||||
sec 1024D/6D9732AC 1999-03-08 Oscar Test (demo key) <oscar@example.net>
|
||||
ssb 1024g/2681619F 1999-03-08
|
||||
sec 1024D/3FF13206 1999-03-08 Papa test (demo key) <papa@example.net>
|
||||
ssb 1024g/63330D9C 1999-03-08
|
||||
sec 1024D/3C661C84 1999-03-08 Quebec Test (demo key) <quebec@example.net>
|
||||
ssb 1024g/A029ACF4 1999-03-08
|
||||
sec 1024D/777FBED3 1999-03-08 Romeo Test (demo key) <romeo@example.net>
|
||||
ssb 1024g/11D102EA 1999-03-08
|
||||
sec 1024D/A3AE3EA1 1999-03-08 Sierra Test (demo key) <sierra@example.net>
|
||||
ssb 1024g/0F1B50B4 1999-03-08
|
||||
sec 1024D/85A81F38 1999-03-08 Tango Test (demo key) <tango@example.net>
|
||||
ssb 1024g/101C0402 1999-03-08
|
||||
sec 1024D/653244D6 1999-03-08 Uniform Test (demo key) <uniform@example.net>
|
||||
ssb 1024g/5522BDB9 1999-03-08
|
||||
sec 1024D/61F04784 1999-03-08 Victor Test (demo key) <victor@example.org>
|
||||
ssb 1024g/07287134 1999-03-08
|
||||
sec 1024D/EC67DBDE 1999-03-08 Whisky Test (demo key) <whisky@example.net>
|
||||
ssb 1024g/FD6E27F6 1999-03-08
|
||||
sec 1024D/567FB34A 1999-03-08 XRay Test (demo key) <xray@example.net>
|
||||
ssb 1024g/41E408BE 1999-03-08
|
||||
sec 1024D/4B11B25F 1999-03-08 Yankee Test (demo key) <yankee@example.net>
|
||||
ssb 1024g/F7B080AD 1999-03-08
|
||||
sec 1024D/54ACD246 1999-03-08 Zulu Test (demo key) <zulu@example.net>
|
||||
ssb 1024g/A172C881 1999-03-08
|
||||
|
||||
-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
Version: GnuPG v0.9.3 (GNU/Linux)
|
||||
Comment: For info see http://www.gnupg.org
|
||||
|
||||
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
|
||||
=P9+G
|
||||
-----END PGP PRIVATE KEY BLOCK-----
|
@ -1,57 +0,0 @@
|
||||
This is a test secret keyring simply stored by GNUPG so that
|
||||
it is easier to make diff files.
|
||||
|
||||
sec 768G/9D266E0F 1998-04-28 Test one (pp=def) <one@test.nowhere.nil>
|
||||
sec 800G/2E5FA4F4 1998-04-28 test two (no pp) <two@test.nowhere.nil>
|
||||
sec 768G/6D11D6D3 1998-04-28 test three (pp=abc) <three@test.nowhere.nil>
|
||||
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
Version: GNUPG v0.2.19b (GNU/Linux)
|
||||
Comment: This is an alpha version!
|
||||
Comment: Use "gpgm --dearmor" for unpacking
|
||||
|
||||
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
|
||||
tW5GlGnLFCLsPQ==
|
||||
=VGBx
|
||||
-----END PGP ARMORED FILE-----
|
@ -1,27 +0,0 @@
|
||||
This is a test secring generated by pgp 5 beta
|
||||
|
||||
Type Bits KeyID Created Expires Algorithm Use
|
||||
sec+ 768 439F02CA 1998-03-17 ---------- DSS Sign and Encrypt
|
||||
sub 768 CB879DE9 1998-03-17 ---------- Diffie-Hellman
|
||||
uid pgp5 test <pgp5@dev.null>
|
||||
|
||||
There is no password on the key
|
||||
|
||||
-----BEGIN PGP ARMORED FILE-----
|
||||
Version: GNUPG v0.2.13a (Linux)
|
||||
Comment: This is an alpha version!
|
||||
Comment: Use "gpgm --dearmor" for unpacking
|
||||
|
||||
lQFbBDUOrE4RAwDbbxWAbWsheUJprK6VryMTpwDiYwMfL+92nrHqSfPqlpMWgDTia8qnpRSXbyEm
|
||||
Sppp/6/Ygp+N3n32Kznq7PjHXiuWLlZGvZMtzmvaMA17y0GY6oLBxS7rhASXIKa9hEUAoP+KBFly
|
||||
qNMdsK8j+ZO0A8rnImGrAwC1ddDme5iZFkTEWHhrtU97sEu2GDkSQB8HdX8CoRcrOz/B2WliF6qf
|
||||
BKhcZPFVBIhKNzjTfY7SEYAZk2zcsCm8elnwSLaGEzxKFNFBqKDNXP+a35spcqsHSGzDVw4VuKMD
|
||||
AJNnAP6skpHlhVAmecLZT9eRzVoOq1ivUIntK2Mh47qsL74q6BBwz2sviPU2Y3pDlbb6Ed0qJAXv
|
||||
dCT24hlfoGoXzkoDInkPJTJeL0gCnwmQPjvXFFd71Cvg5LaL4lIQLQAAn3GbgsWo+7E/hWakzstp
|
||||
TXzI2kDIDIm0GXBncDUgdGVzdCA8cGdwNUBkZXYubnVsbD6dAO8ENQ6sVhADAP8Fa5TbD6k8VmW1
|
||||
IjK1DfDI0xUdsVIbk8N3Hb0YIlT1E/6tZdfiNwqaKVQcf17gJIObBwfNM3OqWYOudmBVd3S6E3Hk
|
||||
u64nW+ZNt7B2toWRgnk6OgHcSDsud4Igjwz/RQACAgL/ToefzlcVKiPuobKfXHDhIUQPTfGic2Az
|
||||
47wkMoYHo9j9ZE7AWaliMdPz4jLyLfqqoU9mH8g+vJhyAc7UnAF2Sk5466FDypdPm5F9PTW3cqqI
|
||||
wJM4WgkSlM8J2hxH4YtlAADlG+pxFXNFuDPmcq6jL6dug2ikZ7hcHLAy7DddSS8OAA==
|
||||
=1UWo
|
||||
-----END PGP ARMORED FILE-----
|
@ -1,16 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
if [ $# != 3 ]; then
|
||||
echo "Usage: signdemokey name user_id user_id_no"
|
||||
exit 1
|
||||
fi
|
||||
name="$1"
|
||||
user_id="$2"
|
||||
user_id_no="$3"
|
||||
|
||||
echo "abc" | ../g10/gpg --options ./options --homedir $name \
|
||||
--sign-key --batch --yes --passphrase-fd 0 $user_id \
|
||||
$user_id_no sign save
|
||||
|
@ -1,22 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
#info Checking signing and encryption for DSA
|
||||
for i in $plain_files $data_files ; do
|
||||
$GPG $dsa_keyrings --always-trust -se -o x --yes \
|
||||
-u "$dsa_usrname1" -r "$dsa_usrname2" $i
|
||||
$GPG $dsa_keyrings -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
for da in ripemd160 sha1; do
|
||||
for i in $plain_files; do
|
||||
$GPG $dsa_keyrings --always-trust -se -o x --yes --digest-algo $da \
|
||||
-u "$dsa_usrname1" -r "$dsa_usrname2" $i
|
||||
$GPG $dsa_keyrings -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
# process only the first one
|
||||
break
|
||||
done
|
||||
done
|
@ -1,13 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
|
||||
#info Checking signing and encryption
|
||||
for i in $plain_files $data_files ; do
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --always-trust \
|
||||
-se -o x --yes -r "$usrname2" $i
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
@ -1,22 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
#info Checking DSA signatures (default digest algo)
|
||||
for i in $plain_files $data_files; do
|
||||
$GPG $dsa_keyrings -s -o x --yes -u $dsa_usrname1 $i
|
||||
$GPG $dsa_keyrings -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
for da in ripemd160 sha1; do
|
||||
for i in $plain_files; do
|
||||
$GPG $dsa_keyrings --digest-algo $da \
|
||||
-s -o x --yes -u $dsa_usrname1 $i
|
||||
$GPG $dsa_keyrings -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
# process only the first one
|
||||
break
|
||||
done
|
||||
done
|
||||
|
@ -1,26 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
#info Checking signatures
|
||||
for i in $plain_files $data_files; do
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 -s -o x --yes $i
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
done
|
||||
|
||||
hash_algo_list="ripemd160 sha1 md5"
|
||||
if have_hash_algo "TIGER192"; then
|
||||
hash_algo_list="$hash_algo_list tiger192"
|
||||
fi
|
||||
|
||||
for da in $hash_algo_list ; do
|
||||
for i in $plain_files; do
|
||||
echo "$usrpass1" | $GPG --passphrase-fd 0 --digest-algo $da \
|
||||
-s -o x --yes $i
|
||||
$GPG -o y --yes x
|
||||
cmp $i y || error "$i: mismatch"
|
||||
# process only the first one
|
||||
break
|
||||
done
|
||||
done
|
@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
. $srcdir/defs.inc || exit 3
|
||||
|
||||
# print the GPG version
|
||||
$GPG --version
|
||||
|
||||
#fixme: check that the output is correct
|
||||
|
1027
cipher/ChangeLog
1027
cipher/ChangeLog
File diff suppressed because it is too large
Load Diff
@ -1,63 +0,0 @@
|
||||
# Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GnuPG.
|
||||
#
|
||||
# GnuPG is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# GnuPG is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
INCLUDES = -I.. -I$(top_srcdir)/include -I$(top_srcdir)/intl
|
||||
|
||||
noinst_LIBRARIES = libcipher.a
|
||||
|
||||
libcipher_a_SOURCES = cipher.c \
|
||||
pubkey.c \
|
||||
md.c \
|
||||
dynload.c \
|
||||
bithelp.h \
|
||||
des.c \
|
||||
twofish.c \
|
||||
blowfish.c \
|
||||
cast5.c \
|
||||
rijndael.c \
|
||||
elgamal.c \
|
||||
elgamal.h \
|
||||
rsa.c rsa.h \
|
||||
primegen.c \
|
||||
random.h \
|
||||
random.c \
|
||||
rand-internal.h \
|
||||
rmd.h \
|
||||
dsa.h \
|
||||
dsa.c \
|
||||
g10c.c \
|
||||
smallprime.c \
|
||||
algorithms.h \
|
||||
rndlinux.c \
|
||||
rndunix.c \
|
||||
rndegd.c \
|
||||
rndw32.c \
|
||||
md5.c \
|
||||
rmd160.c \
|
||||
sha1.c \
|
||||
tiger.c
|
||||
|
||||
EXTRA_libcipher_a_SOURCES = idea-stub.c
|
||||
|
||||
libcipher_a_DEPENDENCIES = @IDEA_O@
|
||||
libcipher_a_LIBADD = @IDEA_O@
|
||||
|
||||
tiger.o: $(srcdir)/tiger.c
|
||||
`echo $(COMPILE) -c $(srcdir)/tiger.c | sed -e 's/-O[2-9s]*/-O1/g' `
|
@ -1,118 +0,0 @@
|
||||
/* algorithms.h - prototypes for algorithm functions.
|
||||
* Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef GNUPG_ALGORITHMS_H
|
||||
#define GNUPG_ALGORITHMS_H 1
|
||||
|
||||
const char *dynload_enum_module_names (int seq);
|
||||
|
||||
|
||||
|
||||
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 )
|
||||
);
|
||||
|
||||
|
||||
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 )
|
||||
);
|
||||
|
||||
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 )
|
||||
);
|
||||
|
||||
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 )
|
||||
);
|
||||
|
||||
|
||||
const char *
|
||||
des_get_info( int algo, size_t *keylen,
|
||||
size_t *blocksize, size_t *contextsize,
|
||||
int (**setkeyf)( void *c, byte *key, unsigned keylen ),
|
||||
void (**encryptf)( void *c, byte *outbuf, byte *inbuf ),
|
||||
void (**decryptf)( void *c, byte *outbuf, byte *inbuf )
|
||||
);
|
||||
|
||||
const char *
|
||||
cast5_get_info( int algo, size_t *keylen,
|
||||
size_t *blocksize, size_t *contextsize,
|
||||
int (**setkeyf)( void *c, byte *key, unsigned keylen ),
|
||||
void (**encryptf)( void *c, byte *outbuf, byte *inbuf ),
|
||||
void (**decryptf)( void *c, byte *outbuf, byte *inbuf )
|
||||
);
|
||||
|
||||
|
||||
const char *
|
||||
blowfish_get_info( int algo, size_t *keylen,
|
||||
size_t *blocksize, size_t *contextsize,
|
||||
int (**setkeyf)( void *c, byte *key, unsigned keylen ),
|
||||
void (**encryptf)( void *c, byte *outbuf, byte *inbuf ),
|
||||
void (**decryptf)( void *c, byte *outbuf, byte *inbuf )
|
||||
);
|
||||
|
||||
const char *
|
||||
twofish_get_info( int algo, size_t *keylen,
|
||||
size_t *blocksize, size_t *contextsize,
|
||||
int (**setkeyf)( void *c, byte *key, unsigned keylen ),
|
||||
void (**encryptf)( void *c, byte *outbuf, byte *inbuf ),
|
||||
void (**decryptf)( void *c, byte *outbuf, byte *inbuf )
|
||||
);
|
||||
|
||||
/* this is just a kludge for the time we have not yet changed the cipher
|
||||
* stuff to the scheme we use for random and digests */
|
||||
const char *
|
||||
rijndael_get_info( int algo, size_t *keylen,
|
||||
size_t *blocksize, size_t *contextsize,
|
||||
int (**setkeyf)( void *c, byte *key, unsigned keylen ),
|
||||
void (**encryptf)( void *c, byte *outbuf, byte *inbuf ),
|
||||
void (**decryptf)( void *c, byte *outbuf, byte *inbuf )
|
||||
);
|
||||
|
||||
const char *
|
||||
idea_get_info( int algo, size_t *keylen,
|
||||
size_t *blocksize, size_t *contextsize,
|
||||
int (**setkeyf)( void *c, byte *key, unsigned keylen ),
|
||||
void (**encryptf)( void *c, byte *outbuf, byte *inbuf ),
|
||||
void (**decryptf)( void *c, byte *outbuf, byte *inbuf )
|
||||
);
|
||||
|
||||
|
||||
|
||||
#endif /*GNUPG_ALGORITHMS_H*/
|
@ -1,41 +0,0 @@
|
||||
/* bithelp.h - Some bit manipulation helpers
|
||||
* Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifndef G10_BITHELP_H
|
||||
#define G10_BITHELP_H
|
||||
|
||||
|
||||
/****************
|
||||
* Rotate a 32 bit integer by n bytes
|
||||
*/
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
static inline u32
|
||||
rol( u32 x, int n)
|
||||
{
|
||||
__asm__("roll %%cl,%0"
|
||||
:"=r" (x)
|
||||
:"0" (x),"c" (n));
|
||||
return x;
|
||||
}
|
||||
#else
|
||||
#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
|
||||
#endif
|
||||
|
||||
|
||||
#endif /*G10_BITHELP_H*/
|
@ -1,632 +0,0 @@
|
||||
/* blowfish.c - Blowfish encryption
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* For a description of the algorithm, see:
|
||||
* Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996.
|
||||
* ISBN 0-471-11709-9. Pages 336 ff.
|
||||
*/
|
||||
|
||||
/* Test values:
|
||||
* key "abcdefghijklmnopqrstuvwxyz";
|
||||
* plain "BLOWFISH"
|
||||
* cipher 32 4E D0 FE F4 13 A2 03
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "types.h"
|
||||
#include "errors.h"
|
||||
#include "algorithms.h"
|
||||
|
||||
|
||||
|
||||
#define CIPHER_ALGO_BLOWFISH 4 /* blowfish 128 bit key */
|
||||
|
||||
#define BLOWFISH_BLOCKSIZE 8
|
||||
#define BLOWFISH_ROUNDS 16
|
||||
|
||||
typedef struct {
|
||||
u32 s0[256];
|
||||
u32 s1[256];
|
||||
u32 s2[256];
|
||||
u32 s3[256];
|
||||
u32 p[BLOWFISH_ROUNDS+2];
|
||||
} BLOWFISH_context;
|
||||
|
||||
static int bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen );
|
||||
static void encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf );
|
||||
static void decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf );
|
||||
|
||||
|
||||
/* precomputed S boxes */
|
||||
static const u32 ks0[256] = {
|
||||
0xD1310BA6,0x98DFB5AC,0x2FFD72DB,0xD01ADFB7,0xB8E1AFED,0x6A267E96,
|
||||
0xBA7C9045,0xF12C7F99,0x24A19947,0xB3916CF7,0x0801F2E2,0x858EFC16,
|
||||
0x636920D8,0x71574E69,0xA458FEA3,0xF4933D7E,0x0D95748F,0x728EB658,
|
||||
0x718BCD58,0x82154AEE,0x7B54A41D,0xC25A59B5,0x9C30D539,0x2AF26013,
|
||||
0xC5D1B023,0x286085F0,0xCA417918,0xB8DB38EF,0x8E79DCB0,0x603A180E,
|
||||
0x6C9E0E8B,0xB01E8A3E,0xD71577C1,0xBD314B27,0x78AF2FDA,0x55605C60,
|
||||
0xE65525F3,0xAA55AB94,0x57489862,0x63E81440,0x55CA396A,0x2AAB10B6,
|
||||
0xB4CC5C34,0x1141E8CE,0xA15486AF,0x7C72E993,0xB3EE1411,0x636FBC2A,
|
||||
0x2BA9C55D,0x741831F6,0xCE5C3E16,0x9B87931E,0xAFD6BA33,0x6C24CF5C,
|
||||
0x7A325381,0x28958677,0x3B8F4898,0x6B4BB9AF,0xC4BFE81B,0x66282193,
|
||||
0x61D809CC,0xFB21A991,0x487CAC60,0x5DEC8032,0xEF845D5D,0xE98575B1,
|
||||
0xDC262302,0xEB651B88,0x23893E81,0xD396ACC5,0x0F6D6FF3,0x83F44239,
|
||||
0x2E0B4482,0xA4842004,0x69C8F04A,0x9E1F9B5E,0x21C66842,0xF6E96C9A,
|
||||
0x670C9C61,0xABD388F0,0x6A51A0D2,0xD8542F68,0x960FA728,0xAB5133A3,
|
||||
0x6EEF0B6C,0x137A3BE4,0xBA3BF050,0x7EFB2A98,0xA1F1651D,0x39AF0176,
|
||||
0x66CA593E,0x82430E88,0x8CEE8619,0x456F9FB4,0x7D84A5C3,0x3B8B5EBE,
|
||||
0xE06F75D8,0x85C12073,0x401A449F,0x56C16AA6,0x4ED3AA62,0x363F7706,
|
||||
0x1BFEDF72,0x429B023D,0x37D0D724,0xD00A1248,0xDB0FEAD3,0x49F1C09B,
|
||||
0x075372C9,0x80991B7B,0x25D479D8,0xF6E8DEF7,0xE3FE501A,0xB6794C3B,
|
||||
0x976CE0BD,0x04C006BA,0xC1A94FB6,0x409F60C4,0x5E5C9EC2,0x196A2463,
|
||||
0x68FB6FAF,0x3E6C53B5,0x1339B2EB,0x3B52EC6F,0x6DFC511F,0x9B30952C,
|
||||
0xCC814544,0xAF5EBD09,0xBEE3D004,0xDE334AFD,0x660F2807,0x192E4BB3,
|
||||
0xC0CBA857,0x45C8740F,0xD20B5F39,0xB9D3FBDB,0x5579C0BD,0x1A60320A,
|
||||
0xD6A100C6,0x402C7279,0x679F25FE,0xFB1FA3CC,0x8EA5E9F8,0xDB3222F8,
|
||||
0x3C7516DF,0xFD616B15,0x2F501EC8,0xAD0552AB,0x323DB5FA,0xFD238760,
|
||||
0x53317B48,0x3E00DF82,0x9E5C57BB,0xCA6F8CA0,0x1A87562E,0xDF1769DB,
|
||||
0xD542A8F6,0x287EFFC3,0xAC6732C6,0x8C4F5573,0x695B27B0,0xBBCA58C8,
|
||||
0xE1FFA35D,0xB8F011A0,0x10FA3D98,0xFD2183B8,0x4AFCB56C,0x2DD1D35B,
|
||||
0x9A53E479,0xB6F84565,0xD28E49BC,0x4BFB9790,0xE1DDF2DA,0xA4CB7E33,
|
||||
0x62FB1341,0xCEE4C6E8,0xEF20CADA,0x36774C01,0xD07E9EFE,0x2BF11FB4,
|
||||
0x95DBDA4D,0xAE909198,0xEAAD8E71,0x6B93D5A0,0xD08ED1D0,0xAFC725E0,
|
||||
0x8E3C5B2F,0x8E7594B7,0x8FF6E2FB,0xF2122B64,0x8888B812,0x900DF01C,
|
||||
0x4FAD5EA0,0x688FC31C,0xD1CFF191,0xB3A8C1AD,0x2F2F2218,0xBE0E1777,
|
||||
0xEA752DFE,0x8B021FA1,0xE5A0CC0F,0xB56F74E8,0x18ACF3D6,0xCE89E299,
|
||||
0xB4A84FE0,0xFD13E0B7,0x7CC43B81,0xD2ADA8D9,0x165FA266,0x80957705,
|
||||
0x93CC7314,0x211A1477,0xE6AD2065,0x77B5FA86,0xC75442F5,0xFB9D35CF,
|
||||
0xEBCDAF0C,0x7B3E89A0,0xD6411BD3,0xAE1E7E49,0x00250E2D,0x2071B35E,
|
||||
0x226800BB,0x57B8E0AF,0x2464369B,0xF009B91E,0x5563911D,0x59DFA6AA,
|
||||
0x78C14389,0xD95A537F,0x207D5BA2,0x02E5B9C5,0x83260376,0x6295CFA9,
|
||||
0x11C81968,0x4E734A41,0xB3472DCA,0x7B14A94A,0x1B510052,0x9A532915,
|
||||
0xD60F573F,0xBC9BC6E4,0x2B60A476,0x81E67400,0x08BA6FB5,0x571BE91F,
|
||||
0xF296EC6B,0x2A0DD915,0xB6636521,0xE7B9F9B6,0xFF34052E,0xC5855664,
|
||||
0x53B02D5D,0xA99F8FA1,0x08BA4799,0x6E85076A };
|
||||
|
||||
static const u32 ks1[256] = {
|
||||
0x4B7A70E9,0xB5B32944,0xDB75092E,0xC4192623,0xAD6EA6B0,0x49A7DF7D,
|
||||
0x9CEE60B8,0x8FEDB266,0xECAA8C71,0x699A17FF,0x5664526C,0xC2B19EE1,
|
||||
0x193602A5,0x75094C29,0xA0591340,0xE4183A3E,0x3F54989A,0x5B429D65,
|
||||
0x6B8FE4D6,0x99F73FD6,0xA1D29C07,0xEFE830F5,0x4D2D38E6,0xF0255DC1,
|
||||
0x4CDD2086,0x8470EB26,0x6382E9C6,0x021ECC5E,0x09686B3F,0x3EBAEFC9,
|
||||
0x3C971814,0x6B6A70A1,0x687F3584,0x52A0E286,0xB79C5305,0xAA500737,
|
||||
0x3E07841C,0x7FDEAE5C,0x8E7D44EC,0x5716F2B8,0xB03ADA37,0xF0500C0D,
|
||||
0xF01C1F04,0x0200B3FF,0xAE0CF51A,0x3CB574B2,0x25837A58,0xDC0921BD,
|
||||
0xD19113F9,0x7CA92FF6,0x94324773,0x22F54701,0x3AE5E581,0x37C2DADC,
|
||||
0xC8B57634,0x9AF3DDA7,0xA9446146,0x0FD0030E,0xECC8C73E,0xA4751E41,
|
||||
0xE238CD99,0x3BEA0E2F,0x3280BBA1,0x183EB331,0x4E548B38,0x4F6DB908,
|
||||
0x6F420D03,0xF60A04BF,0x2CB81290,0x24977C79,0x5679B072,0xBCAF89AF,
|
||||
0xDE9A771F,0xD9930810,0xB38BAE12,0xDCCF3F2E,0x5512721F,0x2E6B7124,
|
||||
0x501ADDE6,0x9F84CD87,0x7A584718,0x7408DA17,0xBC9F9ABC,0xE94B7D8C,
|
||||
0xEC7AEC3A,0xDB851DFA,0x63094366,0xC464C3D2,0xEF1C1847,0x3215D908,
|
||||
0xDD433B37,0x24C2BA16,0x12A14D43,0x2A65C451,0x50940002,0x133AE4DD,
|
||||
0x71DFF89E,0x10314E55,0x81AC77D6,0x5F11199B,0x043556F1,0xD7A3C76B,
|
||||
0x3C11183B,0x5924A509,0xF28FE6ED,0x97F1FBFA,0x9EBABF2C,0x1E153C6E,
|
||||
0x86E34570,0xEAE96FB1,0x860E5E0A,0x5A3E2AB3,0x771FE71C,0x4E3D06FA,
|
||||
0x2965DCB9,0x99E71D0F,0x803E89D6,0x5266C825,0x2E4CC978,0x9C10B36A,
|
||||
0xC6150EBA,0x94E2EA78,0xA5FC3C53,0x1E0A2DF4,0xF2F74EA7,0x361D2B3D,
|
||||
0x1939260F,0x19C27960,0x5223A708,0xF71312B6,0xEBADFE6E,0xEAC31F66,
|
||||
0xE3BC4595,0xA67BC883,0xB17F37D1,0x018CFF28,0xC332DDEF,0xBE6C5AA5,
|
||||
0x65582185,0x68AB9802,0xEECEA50F,0xDB2F953B,0x2AEF7DAD,0x5B6E2F84,
|
||||
0x1521B628,0x29076170,0xECDD4775,0x619F1510,0x13CCA830,0xEB61BD96,
|
||||
0x0334FE1E,0xAA0363CF,0xB5735C90,0x4C70A239,0xD59E9E0B,0xCBAADE14,
|
||||
0xEECC86BC,0x60622CA7,0x9CAB5CAB,0xB2F3846E,0x648B1EAF,0x19BDF0CA,
|
||||
0xA02369B9,0x655ABB50,0x40685A32,0x3C2AB4B3,0x319EE9D5,0xC021B8F7,
|
||||
0x9B540B19,0x875FA099,0x95F7997E,0x623D7DA8,0xF837889A,0x97E32D77,
|
||||
0x11ED935F,0x16681281,0x0E358829,0xC7E61FD6,0x96DEDFA1,0x7858BA99,
|
||||
0x57F584A5,0x1B227263,0x9B83C3FF,0x1AC24696,0xCDB30AEB,0x532E3054,
|
||||
0x8FD948E4,0x6DBC3128,0x58EBF2EF,0x34C6FFEA,0xFE28ED61,0xEE7C3C73,
|
||||
0x5D4A14D9,0xE864B7E3,0x42105D14,0x203E13E0,0x45EEE2B6,0xA3AAABEA,
|
||||
0xDB6C4F15,0xFACB4FD0,0xC742F442,0xEF6ABBB5,0x654F3B1D,0x41CD2105,
|
||||
0xD81E799E,0x86854DC7,0xE44B476A,0x3D816250,0xCF62A1F2,0x5B8D2646,
|
||||
0xFC8883A0,0xC1C7B6A3,0x7F1524C3,0x69CB7492,0x47848A0B,0x5692B285,
|
||||
0x095BBF00,0xAD19489D,0x1462B174,0x23820E00,0x58428D2A,0x0C55F5EA,
|
||||
0x1DADF43E,0x233F7061,0x3372F092,0x8D937E41,0xD65FECF1,0x6C223BDB,
|
||||
0x7CDE3759,0xCBEE7460,0x4085F2A7,0xCE77326E,0xA6078084,0x19F8509E,
|
||||
0xE8EFD855,0x61D99735,0xA969A7AA,0xC50C06C2,0x5A04ABFC,0x800BCADC,
|
||||
0x9E447A2E,0xC3453484,0xFDD56705,0x0E1E9EC9,0xDB73DBD3,0x105588CD,
|
||||
0x675FDA79,0xE3674340,0xC5C43465,0x713E38D8,0x3D28F89E,0xF16DFF20,
|
||||
0x153E21E7,0x8FB03D4A,0xE6E39F2B,0xDB83ADF7 };
|
||||
|
||||
static const u32 ks2[256] = {
|
||||
0xE93D5A68,0x948140F7,0xF64C261C,0x94692934,0x411520F7,0x7602D4F7,
|
||||
0xBCF46B2E,0xD4A20068,0xD4082471,0x3320F46A,0x43B7D4B7,0x500061AF,
|
||||
0x1E39F62E,0x97244546,0x14214F74,0xBF8B8840,0x4D95FC1D,0x96B591AF,
|
||||
0x70F4DDD3,0x66A02F45,0xBFBC09EC,0x03BD9785,0x7FAC6DD0,0x31CB8504,
|
||||
0x96EB27B3,0x55FD3941,0xDA2547E6,0xABCA0A9A,0x28507825,0x530429F4,
|
||||
0x0A2C86DA,0xE9B66DFB,0x68DC1462,0xD7486900,0x680EC0A4,0x27A18DEE,
|
||||
0x4F3FFEA2,0xE887AD8C,0xB58CE006,0x7AF4D6B6,0xAACE1E7C,0xD3375FEC,
|
||||
0xCE78A399,0x406B2A42,0x20FE9E35,0xD9F385B9,0xEE39D7AB,0x3B124E8B,
|
||||
0x1DC9FAF7,0x4B6D1856,0x26A36631,0xEAE397B2,0x3A6EFA74,0xDD5B4332,
|
||||
0x6841E7F7,0xCA7820FB,0xFB0AF54E,0xD8FEB397,0x454056AC,0xBA489527,
|
||||
0x55533A3A,0x20838D87,0xFE6BA9B7,0xD096954B,0x55A867BC,0xA1159A58,
|
||||
0xCCA92963,0x99E1DB33,0xA62A4A56,0x3F3125F9,0x5EF47E1C,0x9029317C,
|
||||
0xFDF8E802,0x04272F70,0x80BB155C,0x05282CE3,0x95C11548,0xE4C66D22,
|
||||
0x48C1133F,0xC70F86DC,0x07F9C9EE,0x41041F0F,0x404779A4,0x5D886E17,
|
||||
0x325F51EB,0xD59BC0D1,0xF2BCC18F,0x41113564,0x257B7834,0x602A9C60,
|
||||
0xDFF8E8A3,0x1F636C1B,0x0E12B4C2,0x02E1329E,0xAF664FD1,0xCAD18115,
|
||||
0x6B2395E0,0x333E92E1,0x3B240B62,0xEEBEB922,0x85B2A20E,0xE6BA0D99,
|
||||
0xDE720C8C,0x2DA2F728,0xD0127845,0x95B794FD,0x647D0862,0xE7CCF5F0,
|
||||
0x5449A36F,0x877D48FA,0xC39DFD27,0xF33E8D1E,0x0A476341,0x992EFF74,
|
||||
0x3A6F6EAB,0xF4F8FD37,0xA812DC60,0xA1EBDDF8,0x991BE14C,0xDB6E6B0D,
|
||||
0xC67B5510,0x6D672C37,0x2765D43B,0xDCD0E804,0xF1290DC7,0xCC00FFA3,
|
||||
0xB5390F92,0x690FED0B,0x667B9FFB,0xCEDB7D9C,0xA091CF0B,0xD9155EA3,
|
||||
0xBB132F88,0x515BAD24,0x7B9479BF,0x763BD6EB,0x37392EB3,0xCC115979,
|
||||
0x8026E297,0xF42E312D,0x6842ADA7,0xC66A2B3B,0x12754CCC,0x782EF11C,
|
||||
0x6A124237,0xB79251E7,0x06A1BBE6,0x4BFB6350,0x1A6B1018,0x11CAEDFA,
|
||||
0x3D25BDD8,0xE2E1C3C9,0x44421659,0x0A121386,0xD90CEC6E,0xD5ABEA2A,
|
||||
0x64AF674E,0xDA86A85F,0xBEBFE988,0x64E4C3FE,0x9DBC8057,0xF0F7C086,
|
||||
0x60787BF8,0x6003604D,0xD1FD8346,0xF6381FB0,0x7745AE04,0xD736FCCC,
|
||||
0x83426B33,0xF01EAB71,0xB0804187,0x3C005E5F,0x77A057BE,0xBDE8AE24,
|
||||
0x55464299,0xBF582E61,0x4E58F48F,0xF2DDFDA2,0xF474EF38,0x8789BDC2,
|
||||
0x5366F9C3,0xC8B38E74,0xB475F255,0x46FCD9B9,0x7AEB2661,0x8B1DDF84,
|
||||
0x846A0E79,0x915F95E2,0x466E598E,0x20B45770,0x8CD55591,0xC902DE4C,
|
||||
0xB90BACE1,0xBB8205D0,0x11A86248,0x7574A99E,0xB77F19B6,0xE0A9DC09,
|
||||
0x662D09A1,0xC4324633,0xE85A1F02,0x09F0BE8C,0x4A99A025,0x1D6EFE10,
|
||||
0x1AB93D1D,0x0BA5A4DF,0xA186F20F,0x2868F169,0xDCB7DA83,0x573906FE,
|
||||
0xA1E2CE9B,0x4FCD7F52,0x50115E01,0xA70683FA,0xA002B5C4,0x0DE6D027,
|
||||
0x9AF88C27,0x773F8641,0xC3604C06,0x61A806B5,0xF0177A28,0xC0F586E0,
|
||||
0x006058AA,0x30DC7D62,0x11E69ED7,0x2338EA63,0x53C2DD94,0xC2C21634,
|
||||
0xBBCBEE56,0x90BCB6DE,0xEBFC7DA1,0xCE591D76,0x6F05E409,0x4B7C0188,
|
||||
0x39720A3D,0x7C927C24,0x86E3725F,0x724D9DB9,0x1AC15BB4,0xD39EB8FC,
|
||||
0xED545578,0x08FCA5B5,0xD83D7CD3,0x4DAD0FC4,0x1E50EF5E,0xB161E6F8,
|
||||
0xA28514D9,0x6C51133C,0x6FD5C7E7,0x56E14EC4,0x362ABFCE,0xDDC6C837,
|
||||
0xD79A3234,0x92638212,0x670EFA8E,0x406000E0 };
|
||||
|
||||
static const u32 ks3[256] = {
|
||||
0x3A39CE37,0xD3FAF5CF,0xABC27737,0x5AC52D1B,0x5CB0679E,0x4FA33742,
|
||||
0xD3822740,0x99BC9BBE,0xD5118E9D,0xBF0F7315,0xD62D1C7E,0xC700C47B,
|
||||
0xB78C1B6B,0x21A19045,0xB26EB1BE,0x6A366EB4,0x5748AB2F,0xBC946E79,
|
||||
0xC6A376D2,0x6549C2C8,0x530FF8EE,0x468DDE7D,0xD5730A1D,0x4CD04DC6,
|
||||
0x2939BBDB,0xA9BA4650,0xAC9526E8,0xBE5EE304,0xA1FAD5F0,0x6A2D519A,
|
||||
0x63EF8CE2,0x9A86EE22,0xC089C2B8,0x43242EF6,0xA51E03AA,0x9CF2D0A4,
|
||||
0x83C061BA,0x9BE96A4D,0x8FE51550,0xBA645BD6,0x2826A2F9,0xA73A3AE1,
|
||||
0x4BA99586,0xEF5562E9,0xC72FEFD3,0xF752F7DA,0x3F046F69,0x77FA0A59,
|
||||
0x80E4A915,0x87B08601,0x9B09E6AD,0x3B3EE593,0xE990FD5A,0x9E34D797,
|
||||
0x2CF0B7D9,0x022B8B51,0x96D5AC3A,0x017DA67D,0xD1CF3ED6,0x7C7D2D28,
|
||||
0x1F9F25CF,0xADF2B89B,0x5AD6B472,0x5A88F54C,0xE029AC71,0xE019A5E6,
|
||||
0x47B0ACFD,0xED93FA9B,0xE8D3C48D,0x283B57CC,0xF8D56629,0x79132E28,
|
||||
0x785F0191,0xED756055,0xF7960E44,0xE3D35E8C,0x15056DD4,0x88F46DBA,
|
||||
0x03A16125,0x0564F0BD,0xC3EB9E15,0x3C9057A2,0x97271AEC,0xA93A072A,
|
||||
0x1B3F6D9B,0x1E6321F5,0xF59C66FB,0x26DCF319,0x7533D928,0xB155FDF5,
|
||||
0x03563482,0x8ABA3CBB,0x28517711,0xC20AD9F8,0xABCC5167,0xCCAD925F,
|
||||
0x4DE81751,0x3830DC8E,0x379D5862,0x9320F991,0xEA7A90C2,0xFB3E7BCE,
|
||||
0x5121CE64,0x774FBE32,0xA8B6E37E,0xC3293D46,0x48DE5369,0x6413E680,
|
||||
0xA2AE0810,0xDD6DB224,0x69852DFD,0x09072166,0xB39A460A,0x6445C0DD,
|
||||
0x586CDECF,0x1C20C8AE,0x5BBEF7DD,0x1B588D40,0xCCD2017F,0x6BB4E3BB,
|
||||
0xDDA26A7E,0x3A59FF45,0x3E350A44,0xBCB4CDD5,0x72EACEA8,0xFA6484BB,
|
||||
0x8D6612AE,0xBF3C6F47,0xD29BE463,0x542F5D9E,0xAEC2771B,0xF64E6370,
|
||||
0x740E0D8D,0xE75B1357,0xF8721671,0xAF537D5D,0x4040CB08,0x4EB4E2CC,
|
||||
0x34D2466A,0x0115AF84,0xE1B00428,0x95983A1D,0x06B89FB4,0xCE6EA048,
|
||||
0x6F3F3B82,0x3520AB82,0x011A1D4B,0x277227F8,0x611560B1,0xE7933FDC,
|
||||
0xBB3A792B,0x344525BD,0xA08839E1,0x51CE794B,0x2F32C9B7,0xA01FBAC9,
|
||||
0xE01CC87E,0xBCC7D1F6,0xCF0111C3,0xA1E8AAC7,0x1A908749,0xD44FBD9A,
|
||||
0xD0DADECB,0xD50ADA38,0x0339C32A,0xC6913667,0x8DF9317C,0xE0B12B4F,
|
||||
0xF79E59B7,0x43F5BB3A,0xF2D519FF,0x27D9459C,0xBF97222C,0x15E6FC2A,
|
||||
0x0F91FC71,0x9B941525,0xFAE59361,0xCEB69CEB,0xC2A86459,0x12BAA8D1,
|
||||
0xB6C1075E,0xE3056A0C,0x10D25065,0xCB03A442,0xE0EC6E0E,0x1698DB3B,
|
||||
0x4C98A0BE,0x3278E964,0x9F1F9532,0xE0D392DF,0xD3A0342B,0x8971F21E,
|
||||
0x1B0A7441,0x4BA3348C,0xC5BE7120,0xC37632D8,0xDF359F8D,0x9B992F2E,
|
||||
0xE60B6F47,0x0FE3F11D,0xE54CDA54,0x1EDAD891,0xCE6279CF,0xCD3E7E6F,
|
||||
0x1618B166,0xFD2C1D05,0x848FD2C5,0xF6FB2299,0xF523F357,0xA6327623,
|
||||
0x93A83531,0x56CCCD02,0xACF08162,0x5A75EBB5,0x6E163697,0x88D273CC,
|
||||
0xDE966292,0x81B949D0,0x4C50901B,0x71C65614,0xE6C6C7BD,0x327A140A,
|
||||
0x45E1D006,0xC3F27B9A,0xC9AA53FD,0x62A80F00,0xBB25BFE2,0x35BDD2F6,
|
||||
0x71126905,0xB2040222,0xB6CBCF7C,0xCD769C2B,0x53113EC0,0x1640E3D3,
|
||||
0x38ABBD60,0x2547ADF0,0xBA38209C,0xF746CE76,0x77AFA1C5,0x20756060,
|
||||
0x85CBFE4E,0x8AE88DD8,0x7AAAF9B0,0x4CF9AA7E,0x1948C25C,0x02FB8A8C,
|
||||
0x01C36AE4,0xD6EBE1F9,0x90D4F869,0xA65CDEA0,0x3F09252D,0xC208E69F,
|
||||
0xB74E6132,0xCE77E25B,0x578FDFE3,0x3AC372E6 };
|
||||
|
||||
static const u32 ps[BLOWFISH_ROUNDS+2] = {
|
||||
0x243F6A88,0x85A308D3,0x13198A2E,0x03707344,0xA4093822,0x299F31D0,
|
||||
0x082EFA98,0xEC4E6C89,0x452821E6,0x38D01377,0xBE5466CF,0x34E90C6C,
|
||||
0xC0AC29B7,0xC97C50DD,0x3F84D5B5,0xB5470917,0x9216D5D9,0x8979FB1B };
|
||||
|
||||
|
||||
|
||||
#if BLOWFISH_ROUNDS != 16
|
||||
static inline u32
|
||||
function_F( BLOWFISH_context *bc, u32 x )
|
||||
{
|
||||
u16 a, b, c, d;
|
||||
|
||||
#ifdef BIG_ENDIAN_HOST
|
||||
a = ((byte*)&x)[0];
|
||||
b = ((byte*)&x)[1];
|
||||
c = ((byte*)&x)[2];
|
||||
d = ((byte*)&x)[3];
|
||||
#else
|
||||
a = ((byte*)&x)[3];
|
||||
b = ((byte*)&x)[2];
|
||||
c = ((byte*)&x)[1];
|
||||
d = ((byte*)&x)[0];
|
||||
#endif
|
||||
|
||||
return ((bc->s0[a] + bc->s1[b]) ^ bc->s2[c] ) + bc->s3[d];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BIG_ENDIAN_HOST
|
||||
#define F(x) ((( s0[((byte*)&x)[0]] + s1[((byte*)&x)[1]]) \
|
||||
^ s2[((byte*)&x)[2]]) + s3[((byte*)&x)[3]] )
|
||||
#else
|
||||
#define F(x) ((( s0[((byte*)&x)[3]] + s1[((byte*)&x)[2]]) \
|
||||
^ s2[((byte*)&x)[1]]) + s3[((byte*)&x)[0]] )
|
||||
#endif
|
||||
#define R(l,r,i) do { l ^= p[i]; r ^= F(l); } while(0)
|
||||
|
||||
static void
|
||||
burn_stack (int bytes)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
memset (buf, 0, sizeof buf);
|
||||
bytes -= sizeof buf;
|
||||
if (bytes > 0)
|
||||
burn_stack (bytes);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_encrypt( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
|
||||
{
|
||||
#if BLOWFISH_ROUNDS == 16
|
||||
u32 xl, xr, *s0, *s1, *s2, *s3, *p;
|
||||
|
||||
xl = *ret_xl;
|
||||
xr = *ret_xr;
|
||||
p = bc->p;
|
||||
s0 = bc->s0;
|
||||
s1 = bc->s1;
|
||||
s2 = bc->s2;
|
||||
s3 = bc->s3;
|
||||
|
||||
R( xl, xr, 0);
|
||||
R( xr, xl, 1);
|
||||
R( xl, xr, 2);
|
||||
R( xr, xl, 3);
|
||||
R( xl, xr, 4);
|
||||
R( xr, xl, 5);
|
||||
R( xl, xr, 6);
|
||||
R( xr, xl, 7);
|
||||
R( xl, xr, 8);
|
||||
R( xr, xl, 9);
|
||||
R( xl, xr, 10);
|
||||
R( xr, xl, 11);
|
||||
R( xl, xr, 12);
|
||||
R( xr, xl, 13);
|
||||
R( xl, xr, 14);
|
||||
R( xr, xl, 15);
|
||||
|
||||
xl ^= p[BLOWFISH_ROUNDS];
|
||||
xr ^= p[BLOWFISH_ROUNDS+1];
|
||||
|
||||
*ret_xl = xr;
|
||||
*ret_xr = xl;
|
||||
|
||||
#else
|
||||
u32 xl, xr, temp, *p;
|
||||
int i;
|
||||
|
||||
xl = *ret_xl;
|
||||
xr = *ret_xr;
|
||||
p = bc->p;
|
||||
|
||||
for(i=0; i < BLOWFISH_ROUNDS; i++ ) {
|
||||
xl ^= p[i];
|
||||
xr ^= function_F(bc, xl);
|
||||
temp = xl;
|
||||
xl = xr;
|
||||
xr = temp;
|
||||
}
|
||||
temp = xl;
|
||||
xl = xr;
|
||||
xr = temp;
|
||||
|
||||
xr ^= p[BLOWFISH_ROUNDS];
|
||||
xl ^= p[BLOWFISH_ROUNDS+1];
|
||||
|
||||
*ret_xl = xl;
|
||||
*ret_xr = xr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
decrypt( BLOWFISH_context *bc, u32 *ret_xl, u32 *ret_xr )
|
||||
{
|
||||
#if BLOWFISH_ROUNDS == 16
|
||||
u32 xl, xr, *s0, *s1, *s2, *s3, *p;
|
||||
|
||||
xl = *ret_xl;
|
||||
xr = *ret_xr;
|
||||
p = bc->p;
|
||||
s0 = bc->s0;
|
||||
s1 = bc->s1;
|
||||
s2 = bc->s2;
|
||||
s3 = bc->s3;
|
||||
|
||||
R( xl, xr, 17);
|
||||
R( xr, xl, 16);
|
||||
R( xl, xr, 15);
|
||||
R( xr, xl, 14);
|
||||
R( xl, xr, 13);
|
||||
R( xr, xl, 12);
|
||||
R( xl, xr, 11);
|
||||
R( xr, xl, 10);
|
||||
R( xl, xr, 9);
|
||||
R( xr, xl, 8);
|
||||
R( xl, xr, 7);
|
||||
R( xr, xl, 6);
|
||||
R( xl, xr, 5);
|
||||
R( xr, xl, 4);
|
||||
R( xl, xr, 3);
|
||||
R( xr, xl, 2);
|
||||
|
||||
xl ^= p[1];
|
||||
xr ^= p[0];
|
||||
|
||||
*ret_xl = xr;
|
||||
*ret_xr = xl;
|
||||
|
||||
#else
|
||||
u32 xl, xr, temp, *p;
|
||||
int i;
|
||||
|
||||
xl = *ret_xl;
|
||||
xr = *ret_xr;
|
||||
p = bc->p;
|
||||
|
||||
for(i=BLOWFISH_ROUNDS+1; i > 1; i-- ) {
|
||||
xl ^= p[i];
|
||||
xr ^= function_F(bc, xl);
|
||||
temp = xl;
|
||||
xl = xr;
|
||||
xr = temp;
|
||||
}
|
||||
|
||||
temp = xl;
|
||||
xl = xr;
|
||||
xr = temp;
|
||||
|
||||
xr ^= p[1];
|
||||
xl ^= p[0];
|
||||
|
||||
*ret_xl = xl;
|
||||
*ret_xr = xr;
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef F
|
||||
#undef R
|
||||
|
||||
static void
|
||||
do_encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
|
||||
{
|
||||
u32 d1, d2;
|
||||
|
||||
d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
|
||||
d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
|
||||
do_encrypt( bc, &d1, &d2 );
|
||||
outbuf[0] = (d1 >> 24) & 0xff;
|
||||
outbuf[1] = (d1 >> 16) & 0xff;
|
||||
outbuf[2] = (d1 >> 8) & 0xff;
|
||||
outbuf[3] = d1 & 0xff;
|
||||
outbuf[4] = (d2 >> 24) & 0xff;
|
||||
outbuf[5] = (d2 >> 16) & 0xff;
|
||||
outbuf[6] = (d2 >> 8) & 0xff;
|
||||
outbuf[7] = d2 & 0xff;
|
||||
}
|
||||
|
||||
static void
|
||||
encrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
|
||||
{
|
||||
do_encrypt_block (bc, outbuf, inbuf);
|
||||
burn_stack (64);
|
||||
}
|
||||
|
||||
static void
|
||||
do_decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
|
||||
{
|
||||
u32 d1, d2;
|
||||
|
||||
d1 = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
|
||||
d2 = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
|
||||
decrypt( bc, &d1, &d2 );
|
||||
outbuf[0] = (d1 >> 24) & 0xff;
|
||||
outbuf[1] = (d1 >> 16) & 0xff;
|
||||
outbuf[2] = (d1 >> 8) & 0xff;
|
||||
outbuf[3] = d1 & 0xff;
|
||||
outbuf[4] = (d2 >> 24) & 0xff;
|
||||
outbuf[5] = (d2 >> 16) & 0xff;
|
||||
outbuf[6] = (d2 >> 8) & 0xff;
|
||||
outbuf[7] = d2 & 0xff;
|
||||
}
|
||||
|
||||
static void
|
||||
decrypt_block( BLOWFISH_context *bc, byte *outbuf, byte *inbuf )
|
||||
{
|
||||
do_decrypt_block (bc, outbuf, inbuf);
|
||||
burn_stack (64);
|
||||
}
|
||||
|
||||
|
||||
static const char*
|
||||
selftest(void)
|
||||
{
|
||||
BLOWFISH_context c;
|
||||
byte plain[] = "BLOWFISH";
|
||||
byte buffer[8];
|
||||
byte plain3[] = { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 };
|
||||
byte key3[] = { 0x41, 0x79, 0x6E, 0xA0, 0x52, 0x61, 0x6E, 0xE4 };
|
||||
byte cipher3[] = { 0xE1, 0x13, 0xF4, 0x10, 0x2C, 0xFC, 0xCE, 0x43 };
|
||||
|
||||
bf_setkey( &c, "abcdefghijklmnopqrstuvwxyz", 26 );
|
||||
encrypt_block( &c, buffer, plain );
|
||||
if( memcmp( buffer, "\x32\x4E\xD0\xFE\xF4\x13\xA2\x03", 8 ) )
|
||||
return "Blowfish selftest failed (1).";
|
||||
decrypt_block( &c, buffer, buffer );
|
||||
if( memcmp( buffer, plain, 8 ) )
|
||||
return "Blowfish selftest failed (2).";
|
||||
|
||||
bf_setkey( &c, key3, 8 );
|
||||
encrypt_block( &c, buffer, plain3 );
|
||||
if( memcmp( buffer, cipher3, 8 ) )
|
||||
return "Blowfish selftest failed (3).";
|
||||
decrypt_block( &c, buffer, buffer );
|
||||
if( memcmp( buffer, plain3, 8 ) )
|
||||
return "Blowfish selftest failed (4).";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef __riscos__
|
||||
/* need to switch off CSE optimisation for Norcroft C (Acorn/Pace) */
|
||||
#pragma no_optimise_cse
|
||||
#endif /* __riscos__ */
|
||||
|
||||
static int
|
||||
do_bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
|
||||
{
|
||||
int i, j;
|
||||
u32 data, datal, datar;
|
||||
static int initialized;
|
||||
static const char *selftest_failed;
|
||||
|
||||
if( !initialized ) {
|
||||
initialized = 1;
|
||||
selftest_failed = selftest();
|
||||
if( selftest_failed )
|
||||
fprintf(stderr,"%s\n", selftest_failed );
|
||||
}
|
||||
if( selftest_failed )
|
||||
return G10ERR_SELFTEST_FAILED;
|
||||
|
||||
for(i=0; i < BLOWFISH_ROUNDS+2; i++ )
|
||||
c->p[i] = ps[i];
|
||||
for(i=0; i < 256; i++ ) {
|
||||
c->s0[i] = ks0[i];
|
||||
c->s1[i] = ks1[i];
|
||||
c->s2[i] = ks2[i];
|
||||
c->s3[i] = ks3[i];
|
||||
}
|
||||
|
||||
for(i=j=0; i < BLOWFISH_ROUNDS+2; i++ ) {
|
||||
#ifdef BIG_ENDIAN_HOST
|
||||
((byte*)&data)[0] = key[j];
|
||||
((byte*)&data)[1] = key[(j+1)%keylen];
|
||||
((byte*)&data)[2] = key[(j+2)%keylen];
|
||||
((byte*)&data)[3] = key[(j+3)%keylen];
|
||||
#else
|
||||
((byte*)&data)[3] = key[j];
|
||||
((byte*)&data)[2] = key[(j+1)%keylen];
|
||||
((byte*)&data)[1] = key[(j+2)%keylen];
|
||||
((byte*)&data)[0] = key[(j+3)%keylen];
|
||||
#endif
|
||||
c->p[i] ^= data;
|
||||
j = (j+4) % keylen;
|
||||
}
|
||||
|
||||
datal = datar = 0;
|
||||
for(i=0; i < BLOWFISH_ROUNDS+2; i += 2 ) {
|
||||
do_encrypt( c, &datal, &datar );
|
||||
c->p[i] = datal;
|
||||
c->p[i+1] = datar;
|
||||
}
|
||||
for(i=0; i < 256; i += 2 ) {
|
||||
do_encrypt( c, &datal, &datar );
|
||||
c->s0[i] = datal;
|
||||
c->s0[i+1] = datar;
|
||||
}
|
||||
for(i=0; i < 256; i += 2 ) {
|
||||
do_encrypt( c, &datal, &datar );
|
||||
c->s1[i] = datal;
|
||||
c->s1[i+1] = datar;
|
||||
}
|
||||
for(i=0; i < 256; i += 2 ) {
|
||||
do_encrypt( c, &datal, &datar );
|
||||
c->s2[i] = datal;
|
||||
c->s2[i+1] = datar;
|
||||
}
|
||||
for(i=0; i < 256; i += 2 ) {
|
||||
do_encrypt( c, &datal, &datar );
|
||||
c->s3[i] = datal;
|
||||
c->s3[i+1] = datar;
|
||||
}
|
||||
|
||||
|
||||
/* Check for weak key. A weak key is a key in which a value in */
|
||||
/* the P-array (here c) occurs more than once per table. */
|
||||
for(i=0; i < 255; i++ ) {
|
||||
for( j=i+1; j < 256; j++) {
|
||||
if( (c->s0[i] == c->s0[j]) || (c->s1[i] == c->s1[j]) ||
|
||||
(c->s2[i] == c->s2[j]) || (c->s3[i] == c->s3[j]) )
|
||||
return G10ERR_WEAK_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __riscos__
|
||||
#pragma optimise_cse
|
||||
#endif /* __riscos__ */
|
||||
|
||||
static int
|
||||
bf_setkey( BLOWFISH_context *c, byte *key, unsigned keylen )
|
||||
{
|
||||
int rc = do_bf_setkey (c, key, keylen);
|
||||
burn_stack (64);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Return some information about the algorithm. We need algo here to
|
||||
* distinguish different flavors of the algorithm.
|
||||
* Returns: A pointer to string describing the algorithm or NULL if
|
||||
* the ALGO is invalid.
|
||||
*/
|
||||
const char *
|
||||
blowfish_get_info( int algo, size_t *keylen,
|
||||
size_t *blocksize, size_t *contextsize,
|
||||
int (**r_setkey)( void *c, byte *key, unsigned keylen ),
|
||||
void (**r_encrypt)( void *c, byte *outbuf, byte *inbuf ),
|
||||
void (**r_decrypt)( void *c, byte *outbuf, byte *inbuf )
|
||||
)
|
||||
{
|
||||
*keylen = 128;
|
||||
*blocksize = BLOWFISH_BLOCKSIZE;
|
||||
*contextsize = sizeof(BLOWFISH_context);
|
||||
*(int (**)(BLOWFISH_context*, byte*, unsigned))r_setkey
|
||||
= bf_setkey;
|
||||
*(void (**)(BLOWFISH_context*, byte*, byte*))r_encrypt
|
||||
= encrypt_block;
|
||||
*(void (**)(BLOWFISH_context*, byte*, byte*))r_decrypt
|
||||
= decrypt_block;
|
||||
|
||||
if( algo == CIPHER_ALGO_BLOWFISH )
|
||||
return "BLOWFISH";
|
||||
return NULL;
|
||||
}
|
||||
|
654
cipher/cast5.c
654
cipher/cast5.c
@ -1,654 +0,0 @@
|
||||
/* cast5.c - CAST5 cipher (RFC2144)
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
/* Test vectors:
|
||||
*
|
||||
* 128-bit key = 01 23 45 67 12 34 56 78 23 45 67 89 34 56 78 9A
|
||||
* plaintext = 01 23 45 67 89 AB CD EF
|
||||
* ciphertext = 23 8B 4F E5 84 7E 44 B2
|
||||
*
|
||||
* 80-bit key = 01 23 45 67 12 34 56 78 23 45
|
||||
* = 01 23 45 67 12 34 56 78 23 45 00 00 00 00 00 00
|
||||
* plaintext = 01 23 45 67 89 AB CD EF
|
||||
* ciphertext = EB 6A 71 1A 2C 02 27 1B
|
||||
*
|
||||
* 40-bit key = 01 23 45 67 12
|
||||
* = 01 23 45 67 12 00 00 00 00 00 00 00 00 00 00 00
|
||||
* plaintext = 01 23 45 67 89 AB CD EF
|
||||
* ciphertext = 7A C8 16 D1 6E 9B 30 2E
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "types.h"
|
||||
#include "errors.h"
|
||||
#include "algorithms.h"
|
||||
|
||||
|
||||
#define CIPHER_ALGO_CAST5 3
|
||||
|
||||
#define CAST5_BLOCKSIZE 8
|
||||
|
||||
typedef struct {
|
||||
u32 Km[16];
|
||||
byte Kr[16];
|
||||
} CAST5_context;
|
||||
|
||||
static int cast_setkey( CAST5_context *c, byte *key, unsigned keylen );
|
||||
static void encrypt_block( CAST5_context *bc, byte *outbuf, byte *inbuf );
|
||||
static void decrypt_block( CAST5_context *bc, byte *outbuf, byte *inbuf );
|
||||
|
||||
|
||||
|
||||
|
||||
static const u32 s1[256] = {
|
||||
0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
|
||||
0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
|
||||
0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
|
||||
0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
|
||||
0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
|
||||
0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
|
||||
0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
|
||||
0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
|
||||
0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
|
||||
0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
|
||||
0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
|
||||
0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
|
||||
0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
|
||||
0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
|
||||
0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
|
||||
0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
|
||||
0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
|
||||
0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
|
||||
0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
|
||||
0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
|
||||
0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
|
||||
0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
|
||||
0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
|
||||
0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
|
||||
0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
|
||||
0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
|
||||
0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
|
||||
0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
|
||||
0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
|
||||
0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
|
||||
0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
|
||||
0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
|
||||
};
|
||||
static const u32 s2[256] = {
|
||||
0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
|
||||
0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
|
||||
0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
|
||||
0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
|
||||
0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
|
||||
0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
|
||||
0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
|
||||
0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
|
||||
0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
|
||||
0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
|
||||
0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
|
||||
0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
|
||||
0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
|
||||
0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
|
||||
0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
|
||||
0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
|
||||
0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
|
||||
0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
|
||||
0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
|
||||
0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
|
||||
0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
|
||||
0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
|
||||
0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
|
||||
0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
|
||||
0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
|
||||
0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
|
||||
0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
|
||||
0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
|
||||
0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
|
||||
0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
|
||||
0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
|
||||
0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1
|
||||
};
|
||||
static const u32 s3[256] = {
|
||||
0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
|
||||
0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
|
||||
0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
|
||||
0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
|
||||
0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
|
||||
0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
|
||||
0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
|
||||
0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
|
||||
0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
|
||||
0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
|
||||
0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
|
||||
0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
|
||||
0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
|
||||
0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
|
||||
0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
|
||||
0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
|
||||
0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
|
||||
0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
|
||||
0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
|
||||
0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
|
||||
0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
|
||||
0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
|
||||
0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
|
||||
0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
|
||||
0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
|
||||
0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
|
||||
0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
|
||||
0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
|
||||
0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
|
||||
0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
|
||||
0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
|
||||
0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783
|
||||
};
|
||||
static const u32 s4[256] = {
|
||||
0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
|
||||
0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
|
||||
0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
|
||||
0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
|
||||
0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
|
||||
0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
|
||||
0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
|
||||
0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
|
||||
0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
|
||||
0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
|
||||
0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
|
||||
0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
|
||||
0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
|
||||
0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
|
||||
0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
|
||||
0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
|
||||
0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
|
||||
0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
|
||||
0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
|
||||
0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
|
||||
0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
|
||||
0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
|
||||
0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
|
||||
0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
|
||||
0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
|
||||
0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
|
||||
0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
|
||||
0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
|
||||
0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
|
||||
0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
|
||||
0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
|
||||
0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
|
||||
};
|
||||
static const u32 s5[256] = {
|
||||
0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
|
||||
0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
|
||||
0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
|
||||
0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
|
||||
0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
|
||||
0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
|
||||
0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
|
||||
0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
|
||||
0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
|
||||
0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
|
||||
0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
|
||||
0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
|
||||
0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
|
||||
0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
|
||||
0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
|
||||
0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
|
||||
0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
|
||||
0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
|
||||
0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
|
||||
0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
|
||||
0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
|
||||
0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
|
||||
0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
|
||||
0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
|
||||
0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
|
||||
0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
|
||||
0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
|
||||
0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
|
||||
0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
|
||||
0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
|
||||
0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
|
||||
0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4
|
||||
};
|
||||
static const u32 s6[256] = {
|
||||
0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
|
||||
0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
|
||||
0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
|
||||
0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
|
||||
0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
|
||||
0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
|
||||
0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
|
||||
0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
|
||||
0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
|
||||
0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
|
||||
0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
|
||||
0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
|
||||
0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
|
||||
0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
|
||||
0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
|
||||
0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
|
||||
0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
|
||||
0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
|
||||
0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
|
||||
0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
|
||||
0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
|
||||
0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
|
||||
0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
|
||||
0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
|
||||
0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
|
||||
0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
|
||||
0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
|
||||
0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
|
||||
0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
|
||||
0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
|
||||
0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
|
||||
0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f
|
||||
};
|
||||
static const u32 s7[256] = {
|
||||
0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
|
||||
0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
|
||||
0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
|
||||
0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
|
||||
0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
|
||||
0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
|
||||
0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
|
||||
0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
|
||||
0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
|
||||
0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
|
||||
0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
|
||||
0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
|
||||
0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
|
||||
0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
|
||||
0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
|
||||
0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
|
||||
0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
|
||||
0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
|
||||
0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
|
||||
0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
|
||||
0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
|
||||
0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
|
||||
0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
|
||||
0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
|
||||
0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
|
||||
0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
|
||||
0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
|
||||
0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
|
||||
0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
|
||||
0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
|
||||
0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
|
||||
0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3
|
||||
};
|
||||
static const u32 s8[256] = {
|
||||
0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
|
||||
0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
|
||||
0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
|
||||
0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
|
||||
0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
|
||||
0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
|
||||
0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
|
||||
0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
|
||||
0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
|
||||
0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
|
||||
0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
|
||||
0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
|
||||
0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
|
||||
0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
|
||||
0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
|
||||
0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
|
||||
0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
|
||||
0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
|
||||
0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
|
||||
0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
|
||||
0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
|
||||
0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
|
||||
0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
|
||||
0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
|
||||
0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
|
||||
0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
|
||||
0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
|
||||
0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
|
||||
0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
|
||||
0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
|
||||
0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
|
||||
0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e
|
||||
};
|
||||
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
static inline u32
|
||||
rol(int n, u32 x)
|
||||
{
|
||||
__asm__("roll %%cl,%0"
|
||||
:"=r" (x)
|
||||
:"0" (x),"c" (n));
|
||||
return x;
|
||||
}
|
||||
#else
|
||||
#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) )
|
||||
#endif
|
||||
|
||||
#define F1(D,m,r) ( (I = ((m) + (D))), (I=rol((r),I)), \
|
||||
(((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) )
|
||||
#define F2(D,m,r) ( (I = ((m) ^ (D))), (I=rol((r),I)), \
|
||||
(((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) )
|
||||
#define F3(D,m,r) ( (I = ((m) - (D))), (I=rol((r),I)), \
|
||||
(((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) )
|
||||
|
||||
static void
|
||||
burn_stack (int bytes)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
memset (buf, 0, sizeof buf);
|
||||
bytes -= sizeof buf;
|
||||
if (bytes > 0)
|
||||
burn_stack (bytes);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
|
||||
{
|
||||
u32 l, r, t;
|
||||
u32 I; /* used by the Fx macros */
|
||||
u32 *Km;
|
||||
byte *Kr;
|
||||
|
||||
Km = c->Km;
|
||||
Kr = c->Kr;
|
||||
|
||||
/* (L0,R0) <-- (m1...m64). (Split the plaintext into left and
|
||||
* right 32-bit halves L0 = m1...m32 and R0 = m33...m64.)
|
||||
*/
|
||||
l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
|
||||
r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
|
||||
|
||||
/* (16 rounds) for i from 1 to 16, compute Li and Ri as follows:
|
||||
* Li = Ri-1;
|
||||
* Ri = Li-1 ^ f(Ri-1,Kmi,Kri), where f is defined in Section 2.2
|
||||
* Rounds 1, 4, 7, 10, 13, and 16 use f function Type 1.
|
||||
* Rounds 2, 5, 8, 11, and 14 use f function Type 2.
|
||||
* Rounds 3, 6, 9, 12, and 15 use f function Type 3.
|
||||
*/
|
||||
|
||||
t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]);
|
||||
|
||||
/* c1...c64 <-- (R16,L16). (Exchange final blocks L16, R16 and
|
||||
* concatenate to form the ciphertext.) */
|
||||
outbuf[0] = (r >> 24) & 0xff;
|
||||
outbuf[1] = (r >> 16) & 0xff;
|
||||
outbuf[2] = (r >> 8) & 0xff;
|
||||
outbuf[3] = r & 0xff;
|
||||
outbuf[4] = (l >> 24) & 0xff;
|
||||
outbuf[5] = (l >> 16) & 0xff;
|
||||
outbuf[6] = (l >> 8) & 0xff;
|
||||
outbuf[7] = l & 0xff;
|
||||
}
|
||||
|
||||
static void
|
||||
encrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
|
||||
{
|
||||
do_encrypt_block (c, outbuf, inbuf);
|
||||
burn_stack (20+4*sizeof(void*));
|
||||
}
|
||||
|
||||
static void
|
||||
do_decrypt_block (CAST5_context *c, byte *outbuf, byte *inbuf )
|
||||
{
|
||||
u32 l, r, t;
|
||||
u32 I;
|
||||
u32 *Km;
|
||||
byte *Kr;
|
||||
|
||||
Km = c->Km;
|
||||
Kr = c->Kr;
|
||||
|
||||
l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3];
|
||||
r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7];
|
||||
|
||||
t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[ 9], Kr[ 9]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[ 8], Kr[ 8]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[ 7], Kr[ 7]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[ 6], Kr[ 6]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[ 5], Kr[ 5]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[ 4], Kr[ 4]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[ 3], Kr[ 3]);
|
||||
t = l; l = r; r = t ^ F3(r, Km[ 2], Kr[ 2]);
|
||||
t = l; l = r; r = t ^ F2(r, Km[ 1], Kr[ 1]);
|
||||
t = l; l = r; r = t ^ F1(r, Km[ 0], Kr[ 0]);
|
||||
|
||||
outbuf[0] = (r >> 24) & 0xff;
|
||||
outbuf[1] = (r >> 16) & 0xff;
|
||||
outbuf[2] = (r >> 8) & 0xff;
|
||||
outbuf[3] = r & 0xff;
|
||||
outbuf[4] = (l >> 24) & 0xff;
|
||||
outbuf[5] = (l >> 16) & 0xff;
|
||||
outbuf[6] = (l >> 8) & 0xff;
|
||||
outbuf[7] = l & 0xff;
|
||||
}
|
||||
|
||||
static void
|
||||
decrypt_block( CAST5_context *c, byte *outbuf, byte *inbuf )
|
||||
{
|
||||
do_decrypt_block (c, outbuf, inbuf);
|
||||
burn_stack (20+4*sizeof(void*));
|
||||
}
|
||||
|
||||
|
||||
static const char*
|
||||
selftest(void)
|
||||
{
|
||||
CAST5_context c;
|
||||
byte key[16] = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
|
||||
0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A };
|
||||
byte plain[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
|
||||
byte cipher[8]= { 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2 };
|
||||
byte buffer[8];
|
||||
|
||||
cast_setkey( &c, key, 16 );
|
||||
encrypt_block( &c, buffer, plain );
|
||||
if( memcmp( buffer, cipher, 8 ) )
|
||||
return "1";
|
||||
decrypt_block( &c, buffer, buffer );
|
||||
if( memcmp( buffer, plain, 8 ) )
|
||||
return "2";
|
||||
|
||||
#if 0 /* full maintenance test */
|
||||
{
|
||||
int i;
|
||||
byte a0[16] = { 0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78,
|
||||
0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A };
|
||||
byte b0[16] = { 0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78,
|
||||
0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A };
|
||||
byte a1[16] = { 0xEE,0xA9,0xD0,0xA2,0x49,0xFD,0x3B,0xA6,
|
||||
0xB3,0x43,0x6F,0xB8,0x9D,0x6D,0xCA,0x92 };
|
||||
byte b1[16] = { 0xB2,0xC9,0x5E,0xB0,0x0C,0x31,0xAD,0x71,
|
||||
0x80,0xAC,0x05,0xB8,0xE8,0x3D,0x69,0x6E };
|
||||
|
||||
for(i=0; i < 1000000; i++ ) {
|
||||
cast_setkey( &c, b0, 16 );
|
||||
encrypt_block( &c, a0, a0 );
|
||||
encrypt_block( &c, a0+8, a0+8 );
|
||||
cast_setkey( &c, a0, 16 );
|
||||
encrypt_block( &c, b0, b0 );
|
||||
encrypt_block( &c, b0+8, b0+8 );
|
||||
}
|
||||
if( memcmp( a0, a1, 16 ) || memcmp( b0, b1, 16 ) )
|
||||
return "3";
|
||||
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
key_schedule( u32 *x, u32 *z, u32 *k )
|
||||
{
|
||||
|
||||
#define xi(i) ((x[(i)/4] >> (8*(3-((i)%4)))) & 0xff)
|
||||
#define zi(i) ((z[(i)/4] >> (8*(3-((i)%4)))) & 0xff)
|
||||
|
||||
z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)];
|
||||
z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)];
|
||||
z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)];
|
||||
z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)];
|
||||
k[0] = s5[zi( 8)]^s6[zi( 9)]^s7[zi( 7)]^s8[zi( 6)]^s5[zi( 2)];
|
||||
k[1] = s5[zi(10)]^s6[zi(11)]^s7[zi( 5)]^s8[zi( 4)]^s6[zi( 6)];
|
||||
k[2] = s5[zi(12)]^s6[zi(13)]^s7[zi( 3)]^s8[zi( 2)]^s7[zi( 9)];
|
||||
k[3] = s5[zi(14)]^s6[zi(15)]^s7[zi( 1)]^s8[zi( 0)]^s8[zi(12)];
|
||||
|
||||
x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)];
|
||||
x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)];
|
||||
x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)];
|
||||
x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)];
|
||||
k[4] = s5[xi( 3)]^s6[xi( 2)]^s7[xi(12)]^s8[xi(13)]^s5[xi( 8)];
|
||||
k[5] = s5[xi( 1)]^s6[xi( 0)]^s7[xi(14)]^s8[xi(15)]^s6[xi(13)];
|
||||
k[6] = s5[xi( 7)]^s6[xi( 6)]^s7[xi( 8)]^s8[xi( 9)]^s7[xi( 3)];
|
||||
k[7] = s5[xi( 5)]^s6[xi( 4)]^s7[xi(10)]^s8[xi(11)]^s8[xi( 7)];
|
||||
|
||||
z[0] = x[0] ^ s5[xi(13)]^s6[xi(15)]^s7[xi(12)]^s8[xi(14)]^s7[xi( 8)];
|
||||
z[1] = x[2] ^ s5[zi( 0)]^s6[zi( 2)]^s7[zi( 1)]^s8[zi( 3)]^s8[xi(10)];
|
||||
z[2] = x[3] ^ s5[zi( 7)]^s6[zi( 6)]^s7[zi( 5)]^s8[zi( 4)]^s5[xi( 9)];
|
||||
z[3] = x[1] ^ s5[zi(10)]^s6[zi( 9)]^s7[zi(11)]^s8[zi( 8)]^s6[xi(11)];
|
||||
k[8] = s5[zi( 3)]^s6[zi( 2)]^s7[zi(12)]^s8[zi(13)]^s5[zi( 9)];
|
||||
k[9] = s5[zi( 1)]^s6[zi( 0)]^s7[zi(14)]^s8[zi(15)]^s6[zi(12)];
|
||||
k[10]= s5[zi( 7)]^s6[zi( 6)]^s7[zi( 8)]^s8[zi( 9)]^s7[zi( 2)];
|
||||
k[11]= s5[zi( 5)]^s6[zi( 4)]^s7[zi(10)]^s8[zi(11)]^s8[zi( 6)];
|
||||
|
||||
x[0] = z[2] ^ s5[zi( 5)]^s6[zi( 7)]^s7[zi( 4)]^s8[zi( 6)]^s7[zi( 0)];
|
||||
x[1] = z[0] ^ s5[xi( 0)]^s6[xi( 2)]^s7[xi( 1)]^s8[xi( 3)]^s8[zi( 2)];
|
||||
x[2] = z[1] ^ s5[xi( 7)]^s6[xi( 6)]^s7[xi( 5)]^s8[xi( 4)]^s5[zi( 1)];
|
||||
x[3] = z[3] ^ s5[xi(10)]^s6[xi( 9)]^s7[xi(11)]^s8[xi( 8)]^s6[zi( 3)];
|
||||
k[12]= s5[xi( 8)]^s6[xi( 9)]^s7[xi( 7)]^s8[xi( 6)]^s5[xi( 3)];
|
||||
k[13]= s5[xi(10)]^s6[xi(11)]^s7[xi( 5)]^s8[xi( 4)]^s6[xi( 7)];
|
||||
k[14]= s5[xi(12)]^s6[xi(13)]^s7[xi( 3)]^s8[xi( 2)]^s7[xi( 8)];
|
||||
k[15]= s5[xi(14)]^s6[xi(15)]^s7[xi( 1)]^s8[xi( 0)]^s8[xi(13)];
|
||||
|
||||
#undef xi
|
||||
#undef zi
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_cast_setkey( CAST5_context *c, byte *key, unsigned keylen )
|
||||
{
|
||||
static int initialized;
|
||||
static const char* selftest_failed;
|
||||
int i;
|
||||
u32 x[4];
|
||||
u32 z[4];
|
||||
u32 k[16];
|
||||
|
||||
if( !initialized ) {
|
||||
initialized = 1;
|
||||
selftest_failed = selftest();
|
||||
if( selftest_failed )
|
||||
fprintf(stderr,"CAST5 selftest failed (%s).\n", selftest_failed );
|
||||
}
|
||||
if( selftest_failed )
|
||||
return G10ERR_SELFTEST_FAILED;
|
||||
|
||||
if( keylen != 16 )
|
||||
return G10ERR_WRONG_KEYLEN;
|
||||
|
||||
x[0] = key[0] << 24 | key[1] << 16 | key[2] << 8 | key[3];
|
||||
x[1] = key[4] << 24 | key[5] << 16 | key[6] << 8 | key[7];
|
||||
x[2] = key[8] << 24 | key[9] << 16 | key[10] << 8 | key[11];
|
||||
x[3] = key[12] << 24 | key[13] << 16 | key[14] << 8 | key[15];
|
||||
|
||||
key_schedule( x, z, k );
|
||||
for(i=0; i < 16; i++ )
|
||||
c->Km[i] = k[i];
|
||||
key_schedule( x, z, k );
|
||||
for(i=0; i < 16; i++ )
|
||||
c->Kr[i] = k[i] & 0x1f;
|
||||
|
||||
memset(&x,0, sizeof x);
|
||||
memset(&z,0, sizeof z);
|
||||
memset(&k,0, sizeof k);
|
||||
|
||||
#undef xi
|
||||
#undef zi
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cast_setkey( CAST5_context *c, byte *key, unsigned keylen )
|
||||
{
|
||||
int rc = do_cast_setkey (c, key, keylen);
|
||||
burn_stack (96+7*sizeof(void*));
|
||||
return rc;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Return some information about the algorithm. We need algo here to
|
||||
* distinguish different flavors of the algorithm.
|
||||
* Returns: A pointer to string describing the algorithm or NULL if
|
||||
* the ALGO is invalid.
|
||||
*/
|
||||
const char *
|
||||
cast5_get_info( int algo, size_t *keylen,
|
||||
size_t *blocksize, size_t *contextsize,
|
||||
int (**r_setkey)( void *c, byte *key, unsigned keylen ),
|
||||
void (**r_encrypt)( void *c, byte *outbuf, byte *inbuf ),
|
||||
void (**r_decrypt)( void *c, byte *outbuf, byte *inbuf )
|
||||
)
|
||||
{
|
||||
*keylen = 128;
|
||||
*blocksize = CAST5_BLOCKSIZE;
|
||||
*contextsize = sizeof(CAST5_context);
|
||||
*(int (**)(CAST5_context*, byte*, unsigned))r_setkey
|
||||
= cast_setkey;
|
||||
*(void (**)(CAST5_context*, byte*, byte*))r_encrypt
|
||||
= encrypt_block;
|
||||
*(void (**)(CAST5_context*, byte*, byte*))r_decrypt
|
||||
= decrypt_block;
|
||||
|
||||
|
||||
if( algo == CIPHER_ALGO_CAST5 )
|
||||
return "CAST5";
|
||||
return NULL;
|
||||
}
|
||||
|
678
cipher/cipher.c
678
cipher/cipher.c
@ -1,678 +0,0 @@
|
||||
/* cipher.c - cipher dispatcher
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include "util.h"
|
||||
#include "errors.h"
|
||||
#include "cipher.h"
|
||||
#include "algorithms.h"
|
||||
|
||||
/* We have support for a DUMMY encryption cipher which comes handy to
|
||||
debug MDCs and similar things. Because this is a bit dangerous it
|
||||
is not enabled. */
|
||||
/*#define ALLOW_DUMMY 1 */
|
||||
|
||||
#define MAX_BLOCKSIZE 16
|
||||
#define TABLE_SIZE 14
|
||||
|
||||
struct cipher_table_s {
|
||||
const char *name;
|
||||
int algo;
|
||||
size_t blocksize;
|
||||
size_t keylen;
|
||||
size_t contextsize; /* allocate this amount of context */
|
||||
int (*setkey)( void *c, byte *key, unsigned keylen );
|
||||
void (*encrypt)( void *c, byte *outbuf, byte *inbuf );
|
||||
void (*decrypt)( void *c, byte *outbuf, byte *inbuf );
|
||||
};
|
||||
|
||||
static struct cipher_table_s cipher_table[TABLE_SIZE];
|
||||
static int disabled_algos[TABLE_SIZE];
|
||||
|
||||
|
||||
struct cipher_handle_s {
|
||||
int algo;
|
||||
int mode;
|
||||
size_t blocksize;
|
||||
byte iv[MAX_BLOCKSIZE]; /* (this should be ulong aligned) */
|
||||
byte lastiv[MAX_BLOCKSIZE];
|
||||
int unused; /* in IV */
|
||||
int (*setkey)( void *c, byte *key, unsigned keylen );
|
||||
void (*encrypt)( void *c, byte *outbuf, byte *inbuf );
|
||||
void (*decrypt)( void *c, byte *outbuf, byte *inbuf );
|
||||
PROPERLY_ALIGNED_TYPE context;
|
||||
};
|
||||
|
||||
|
||||
#ifdef ALLOW_DUMMY
|
||||
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(); }
|
||||
#ifdef __GNUC__
|
||||
# warning DUMMY cipher module is enabled
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/****************
|
||||
* Put the static entries into the table.
|
||||
*/
|
||||
static void
|
||||
setup_cipher_table(void)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
cipher_table[i].algo = CIPHER_ALGO_RIJNDAEL;
|
||||
cipher_table[i].name = rijndael_get_info( cipher_table[i].algo,
|
||||
&cipher_table[i].keylen,
|
||||
&cipher_table[i].blocksize,
|
||||
&cipher_table[i].contextsize,
|
||||
&cipher_table[i].setkey,
|
||||
&cipher_table[i].encrypt,
|
||||
&cipher_table[i].decrypt );
|
||||
if( !cipher_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
cipher_table[i].algo = CIPHER_ALGO_RIJNDAEL192;
|
||||
cipher_table[i].name = rijndael_get_info( cipher_table[i].algo,
|
||||
&cipher_table[i].keylen,
|
||||
&cipher_table[i].blocksize,
|
||||
&cipher_table[i].contextsize,
|
||||
&cipher_table[i].setkey,
|
||||
&cipher_table[i].encrypt,
|
||||
&cipher_table[i].decrypt );
|
||||
if( !cipher_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
cipher_table[i].algo = CIPHER_ALGO_RIJNDAEL256;
|
||||
cipher_table[i].name = rijndael_get_info( cipher_table[i].algo,
|
||||
&cipher_table[i].keylen,
|
||||
&cipher_table[i].blocksize,
|
||||
&cipher_table[i].contextsize,
|
||||
&cipher_table[i].setkey,
|
||||
&cipher_table[i].encrypt,
|
||||
&cipher_table[i].decrypt );
|
||||
if( !cipher_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
cipher_table[i].algo = CIPHER_ALGO_TWOFISH;
|
||||
cipher_table[i].name = twofish_get_info( cipher_table[i].algo,
|
||||
&cipher_table[i].keylen,
|
||||
&cipher_table[i].blocksize,
|
||||
&cipher_table[i].contextsize,
|
||||
&cipher_table[i].setkey,
|
||||
&cipher_table[i].encrypt,
|
||||
&cipher_table[i].decrypt );
|
||||
if( !cipher_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
cipher_table[i].algo = CIPHER_ALGO_BLOWFISH;
|
||||
cipher_table[i].name = blowfish_get_info( cipher_table[i].algo,
|
||||
&cipher_table[i].keylen,
|
||||
&cipher_table[i].blocksize,
|
||||
&cipher_table[i].contextsize,
|
||||
&cipher_table[i].setkey,
|
||||
&cipher_table[i].encrypt,
|
||||
&cipher_table[i].decrypt );
|
||||
if( !cipher_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
cipher_table[i].algo = CIPHER_ALGO_CAST5;
|
||||
cipher_table[i].name = cast5_get_info( cipher_table[i].algo,
|
||||
&cipher_table[i].keylen,
|
||||
&cipher_table[i].blocksize,
|
||||
&cipher_table[i].contextsize,
|
||||
&cipher_table[i].setkey,
|
||||
&cipher_table[i].encrypt,
|
||||
&cipher_table[i].decrypt );
|
||||
if( !cipher_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
cipher_table[i].algo = CIPHER_ALGO_3DES;
|
||||
cipher_table[i].name = des_get_info( cipher_table[i].algo,
|
||||
&cipher_table[i].keylen,
|
||||
&cipher_table[i].blocksize,
|
||||
&cipher_table[i].contextsize,
|
||||
&cipher_table[i].setkey,
|
||||
&cipher_table[i].encrypt,
|
||||
&cipher_table[i].decrypt );
|
||||
if( !cipher_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
cipher_table[i].algo = CIPHER_ALGO_IDEA;
|
||||
cipher_table[i].name = idea_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)
|
||||
i++; /* Note that IDEA is usually not available. */
|
||||
|
||||
#ifdef ALLOW_DUMMY
|
||||
cipher_table[i].algo = CIPHER_ALGO_DUMMY;
|
||||
cipher_table[i].name = "DUMMY";
|
||||
cipher_table[i].blocksize = 8;
|
||||
cipher_table[i].keylen = 128;
|
||||
cipher_table[i].contextsize = 0;
|
||||
cipher_table[i].setkey = dummy_setkey;
|
||||
cipher_table[i].encrypt = dummy_encrypt_block;
|
||||
cipher_table[i].decrypt = dummy_decrypt_block;
|
||||
i++;
|
||||
#endif
|
||||
|
||||
for( ; i < TABLE_SIZE; i++ )
|
||||
cipher_table[i].name = NULL;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Try to load all modules and return true if new modules are available
|
||||
*/
|
||||
static int
|
||||
load_cipher_modules(void)
|
||||
{
|
||||
static int initialized = 0;
|
||||
|
||||
if (!initialized )
|
||||
{
|
||||
setup_cipher_table(); /* load static modules on the first call */
|
||||
initialized = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Map a string to the cipher algo
|
||||
*/
|
||||
int
|
||||
string_to_cipher_algo( const char *string )
|
||||
{
|
||||
int i;
|
||||
const char *s;
|
||||
|
||||
/* kludge to alias RIJNDAEL to AES */
|
||||
if ( *string == 'R' || *string == 'r')
|
||||
{
|
||||
if (!ascii_strcasecmp (string, "RIJNDAEL"))
|
||||
string = "AES";
|
||||
else if (!ascii_strcasecmp (string, "RIJNDAEL192"))
|
||||
string = "AES192";
|
||||
else if (!ascii_strcasecmp (string, "RIJNDAEL256"))
|
||||
string = "AES256";
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
for(i=0; (s=cipher_table[i].name); i++ )
|
||||
{
|
||||
if( !ascii_strcasecmp( s, string ) )
|
||||
return cipher_table[i].algo;
|
||||
}
|
||||
} while( load_cipher_modules() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* Map a cipher algo to a string
|
||||
*/
|
||||
const char *
|
||||
cipher_algo_to_string( int algo )
|
||||
{
|
||||
int i;
|
||||
|
||||
do {
|
||||
for(i=0; cipher_table[i].name; i++ )
|
||||
if( cipher_table[i].algo == algo )
|
||||
return cipher_table[i].name;
|
||||
} while( load_cipher_modules() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
disable_cipher_algo( int algo )
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i < DIM(disabled_algos); i++ ) {
|
||||
if( !disabled_algos[i] || disabled_algos[i] == algo ) {
|
||||
disabled_algos[i] = algo;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* fixme: we should use a linked list */
|
||||
log_fatal("can't disable cipher algo %d: table full\n", algo );
|
||||
}
|
||||
|
||||
/****************
|
||||
* Return 0 if the cipher algo is available
|
||||
*/
|
||||
int
|
||||
check_cipher_algo( int algo )
|
||||
{
|
||||
int i;
|
||||
|
||||
do {
|
||||
for(i=0; cipher_table[i].name; i++ )
|
||||
if( cipher_table[i].algo == algo ) {
|
||||
for(i=0; i < DIM(disabled_algos); i++ ) {
|
||||
if( disabled_algos[i] == algo )
|
||||
return G10ERR_CIPHER_ALGO;
|
||||
}
|
||||
return 0; /* okay */
|
||||
}
|
||||
} while( load_cipher_modules() );
|
||||
return G10ERR_CIPHER_ALGO;
|
||||
}
|
||||
|
||||
|
||||
unsigned
|
||||
cipher_get_keylen( int algo )
|
||||
{
|
||||
int i;
|
||||
unsigned len = 0;
|
||||
|
||||
do {
|
||||
for(i=0; cipher_table[i].name; i++ ) {
|
||||
if( cipher_table[i].algo == algo ) {
|
||||
len = cipher_table[i].keylen;
|
||||
if( !len )
|
||||
log_bug("cipher %d w/o key length\n", algo );
|
||||
return len;
|
||||
}
|
||||
}
|
||||
} while( load_cipher_modules() );
|
||||
log_bug("cipher %d not found\n", algo );
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned
|
||||
cipher_get_blocksize( int algo )
|
||||
{
|
||||
int i;
|
||||
unsigned len = 0;
|
||||
|
||||
do {
|
||||
for(i=0; cipher_table[i].name; i++ ) {
|
||||
if( cipher_table[i].algo == algo ) {
|
||||
len = cipher_table[i].blocksize;
|
||||
if( !len )
|
||||
log_bug("cipher %d w/o blocksize\n", algo );
|
||||
return len;
|
||||
}
|
||||
}
|
||||
} while( load_cipher_modules() );
|
||||
log_bug("cipher %d not found\n", algo );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Open a cipher handle for use with algorithm ALGO, in mode MODE
|
||||
* and put it into secure memory if SECURE is true.
|
||||
*/
|
||||
CIPHER_HANDLE
|
||||
cipher_open( int algo, int mode, int secure )
|
||||
{
|
||||
CIPHER_HANDLE hd;
|
||||
int i;
|
||||
|
||||
fast_random_poll();
|
||||
do {
|
||||
for(i=0; cipher_table[i].name; i++ )
|
||||
if( cipher_table[i].algo == algo )
|
||||
break;
|
||||
} while( !cipher_table[i].name && load_cipher_modules() );
|
||||
if( !cipher_table[i].name ) {
|
||||
log_fatal("cipher_open: algorithm %d not available\n", algo );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ? perform selftest here and mark this with a flag in cipher_table ? */
|
||||
|
||||
hd = secure ? m_alloc_secure_clear( sizeof *hd
|
||||
+ cipher_table[i].contextsize
|
||||
- sizeof(PROPERLY_ALIGNED_TYPE) )
|
||||
: m_alloc_clear( sizeof *hd + cipher_table[i].contextsize
|
||||
- sizeof(PROPERLY_ALIGNED_TYPE) );
|
||||
hd->algo = algo;
|
||||
hd->blocksize = cipher_table[i].blocksize;
|
||||
hd->setkey = cipher_table[i].setkey;
|
||||
hd->encrypt = cipher_table[i].encrypt;
|
||||
hd->decrypt = cipher_table[i].decrypt;
|
||||
|
||||
if( mode == CIPHER_MODE_AUTO_CFB ) {
|
||||
if( algo >= 100 )
|
||||
hd->mode = CIPHER_MODE_CFB;
|
||||
else
|
||||
hd->mode = CIPHER_MODE_PHILS_CFB;
|
||||
}
|
||||
else
|
||||
hd->mode = mode;
|
||||
|
||||
#ifdef ALLOW_DUMMY
|
||||
if( algo == CIPHER_ALGO_DUMMY )
|
||||
hd->mode = CIPHER_MODE_DUMMY;
|
||||
#endif
|
||||
|
||||
return hd;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cipher_close( CIPHER_HANDLE c )
|
||||
{
|
||||
m_free(c);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
cipher_setkey( CIPHER_HANDLE c, byte *key, unsigned keylen )
|
||||
{
|
||||
return (*c->setkey)( &c->context.c, key, keylen );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
cipher_setiv( CIPHER_HANDLE c, const byte *iv, unsigned ivlen )
|
||||
{
|
||||
memset( c->iv, 0, c->blocksize );
|
||||
if( iv ) {
|
||||
if( ivlen != c->blocksize )
|
||||
log_info("WARNING: cipher_setiv: ivlen=%u blklen=%u\n",
|
||||
ivlen, (unsigned)c->blocksize );
|
||||
if( ivlen > c->blocksize )
|
||||
ivlen = c->blocksize;
|
||||
memcpy( c->iv, iv, ivlen );
|
||||
}
|
||||
c->unused = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
do_ecb_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks )
|
||||
{
|
||||
unsigned n;
|
||||
|
||||
for(n=0; n < nblocks; n++ ) {
|
||||
(*c->encrypt)( &c->context.c, outbuf, inbuf );
|
||||
inbuf += c->blocksize;
|
||||
outbuf += c->blocksize;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_ecb_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks )
|
||||
{
|
||||
unsigned n;
|
||||
|
||||
for(n=0; n < nblocks; n++ ) {
|
||||
(*c->decrypt)( &c->context.c, outbuf, inbuf );
|
||||
inbuf += c->blocksize;
|
||||
outbuf += c->blocksize;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_cbc_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks )
|
||||
{
|
||||
unsigned int n;
|
||||
byte *ivp;
|
||||
int i;
|
||||
size_t blocksize = c->blocksize;
|
||||
|
||||
for(n=0; n < nblocks; n++ ) {
|
||||
/* fixme: the xor should works on words and not on
|
||||
* bytes. Maybe it is a good idea to enhance the cipher backend
|
||||
* API to allow for CBC handling in the backend */
|
||||
for(ivp=c->iv,i=0; i < blocksize; i++ )
|
||||
outbuf[i] = inbuf[i] ^ *ivp++;
|
||||
(*c->encrypt)( &c->context.c, outbuf, outbuf );
|
||||
memcpy(c->iv, outbuf, blocksize );
|
||||
inbuf += c->blocksize;
|
||||
outbuf += c->blocksize;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_cbc_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks )
|
||||
{
|
||||
unsigned int n;
|
||||
byte *ivp;
|
||||
int i;
|
||||
size_t blocksize = c->blocksize;
|
||||
|
||||
for(n=0; n < nblocks; n++ ) {
|
||||
/* because outbuf and inbuf might be the same, we have
|
||||
* to save the original ciphertext block. We use lastiv
|
||||
* for this here because it is not used otherwise */
|
||||
memcpy(c->lastiv, inbuf, blocksize );
|
||||
(*c->decrypt)( &c->context.c, outbuf, inbuf );
|
||||
for(ivp=c->iv,i=0; i < blocksize; i++ )
|
||||
outbuf[i] ^= *ivp++;
|
||||
memcpy(c->iv, c->lastiv, blocksize );
|
||||
inbuf += c->blocksize;
|
||||
outbuf += c->blocksize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_cfb_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
|
||||
{
|
||||
byte *ivp;
|
||||
size_t blocksize = c->blocksize;
|
||||
|
||||
if( nbytes <= c->unused ) {
|
||||
/* short enough to be encoded by the remaining XOR mask */
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
for(ivp=c->iv+c->blocksize - c->unused; nbytes; nbytes--, c->unused-- )
|
||||
*outbuf++ = (*ivp++ ^= *inbuf++);
|
||||
return;
|
||||
}
|
||||
|
||||
if( c->unused ) {
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
nbytes -= c->unused;
|
||||
for(ivp=c->iv+blocksize - c->unused; c->unused; c->unused-- )
|
||||
*outbuf++ = (*ivp++ ^= *inbuf++);
|
||||
}
|
||||
|
||||
/* now we can process complete blocks */
|
||||
while( nbytes >= blocksize ) {
|
||||
int i;
|
||||
/* encrypt the IV (and save the current one) */
|
||||
memcpy( c->lastiv, c->iv, blocksize );
|
||||
(*c->encrypt)( &c->context.c, c->iv, c->iv );
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
for(ivp=c->iv,i=0; i < blocksize; i++ )
|
||||
*outbuf++ = (*ivp++ ^= *inbuf++);
|
||||
nbytes -= blocksize;
|
||||
}
|
||||
if( nbytes ) { /* process the remaining bytes */
|
||||
/* encrypt the IV (and save the current one) */
|
||||
memcpy( c->lastiv, c->iv, blocksize );
|
||||
(*c->encrypt)( &c->context.c, c->iv, c->iv );
|
||||
c->unused = blocksize;
|
||||
/* and apply the xor */
|
||||
c->unused -= nbytes;
|
||||
for(ivp=c->iv; nbytes; nbytes-- )
|
||||
*outbuf++ = (*ivp++ ^= *inbuf++);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_cfb_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
|
||||
{
|
||||
byte *ivp;
|
||||
ulong temp;
|
||||
size_t blocksize = c->blocksize;
|
||||
|
||||
if( nbytes <= c->unused ) {
|
||||
/* short enough to be encoded by the remaining XOR mask */
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
for(ivp=c->iv+blocksize - c->unused; nbytes; nbytes--,c->unused--){
|
||||
temp = *inbuf++;
|
||||
*outbuf++ = *ivp ^ temp;
|
||||
*ivp++ = temp;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if( c->unused ) {
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
nbytes -= c->unused;
|
||||
for(ivp=c->iv+blocksize - c->unused; c->unused; c->unused-- ) {
|
||||
temp = *inbuf++;
|
||||
*outbuf++ = *ivp ^ temp;
|
||||
*ivp++ = temp;
|
||||
}
|
||||
}
|
||||
|
||||
/* now we can process complete blocks */
|
||||
while( nbytes >= blocksize ) {
|
||||
int i;
|
||||
/* encrypt the IV (and save the current one) */
|
||||
memcpy( c->lastiv, c->iv, blocksize );
|
||||
(*c->encrypt)( &c->context.c, c->iv, c->iv );
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
for(ivp=c->iv,i=0; i < blocksize; i++ ) {
|
||||
temp = *inbuf++;
|
||||
*outbuf++ = *ivp ^ temp;
|
||||
*ivp++ = temp;
|
||||
}
|
||||
nbytes -= blocksize;
|
||||
}
|
||||
if( nbytes ) { /* process the remaining bytes */
|
||||
/* encrypt the IV (and save the current one) */
|
||||
memcpy( c->lastiv, c->iv, blocksize );
|
||||
(*c->encrypt)( &c->context.c, c->iv, c->iv );
|
||||
c->unused = blocksize;
|
||||
/* and apply the xor */
|
||||
c->unused -= nbytes;
|
||||
for(ivp=c->iv; nbytes; nbytes-- ) {
|
||||
temp = *inbuf++;
|
||||
*outbuf++ = *ivp ^ temp;
|
||||
*ivp++ = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Encrypt INBUF to OUTBUF with the mode selected at open.
|
||||
* inbuf and outbuf may overlap or be the same.
|
||||
* Depending on the mode some some contraints apply to NBYTES.
|
||||
*/
|
||||
void
|
||||
cipher_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
|
||||
{
|
||||
switch( c->mode ) {
|
||||
case CIPHER_MODE_ECB:
|
||||
assert(!(nbytes%c->blocksize));
|
||||
do_ecb_encrypt(c, outbuf, inbuf, nbytes/c->blocksize );
|
||||
break;
|
||||
case CIPHER_MODE_CBC:
|
||||
assert(!(nbytes%c->blocksize));
|
||||
do_cbc_encrypt(c, outbuf, inbuf, nbytes/c->blocksize );
|
||||
break;
|
||||
case CIPHER_MODE_CFB:
|
||||
case CIPHER_MODE_PHILS_CFB:
|
||||
do_cfb_encrypt(c, outbuf, inbuf, nbytes );
|
||||
break;
|
||||
#ifdef ALLOW_DUMMY
|
||||
case CIPHER_MODE_DUMMY:
|
||||
if( inbuf != outbuf )
|
||||
memmove( outbuf, inbuf, nbytes );
|
||||
break;
|
||||
#endif
|
||||
default: log_fatal("cipher_encrypt: invalid mode %d\n", c->mode );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Decrypt INBUF to OUTBUF with the mode selected at open.
|
||||
* inbuf and outbuf may overlap or be the same.
|
||||
* Depending on the mode some some contraints apply to NBYTES.
|
||||
*/
|
||||
void
|
||||
cipher_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
|
||||
{
|
||||
switch( c->mode ) {
|
||||
case CIPHER_MODE_ECB:
|
||||
assert(!(nbytes%c->blocksize));
|
||||
do_ecb_decrypt(c, outbuf, inbuf, nbytes/c->blocksize );
|
||||
break;
|
||||
case CIPHER_MODE_CBC:
|
||||
assert(!(nbytes%c->blocksize));
|
||||
do_cbc_decrypt(c, outbuf, inbuf, nbytes/c->blocksize );
|
||||
break;
|
||||
case CIPHER_MODE_CFB:
|
||||
case CIPHER_MODE_PHILS_CFB:
|
||||
do_cfb_decrypt(c, outbuf, inbuf, nbytes );
|
||||
break;
|
||||
#ifdef ALLOW_DUMMY
|
||||
case CIPHER_MODE_DUMMY:
|
||||
if( inbuf != outbuf )
|
||||
memmove( outbuf, inbuf, nbytes );
|
||||
break;
|
||||
#endif
|
||||
default: log_fatal("cipher_decrypt: invalid mode %d\n", c->mode );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Used for PGP's somewhat strange CFB mode. Only works if
|
||||
* the handle is in PHILS_CFB mode
|
||||
*/
|
||||
void
|
||||
cipher_sync( CIPHER_HANDLE c )
|
||||
{
|
||||
if( c->mode == CIPHER_MODE_PHILS_CFB && c->unused ) {
|
||||
memmove(c->iv + c->unused, c->iv, c->blocksize - c->unused );
|
||||
memcpy(c->iv, c->lastiv + c->blocksize - c->unused, c->unused);
|
||||
c->unused = 0;
|
||||
}
|
||||
}
|
||||
|
1024
cipher/des.c
1024
cipher/des.c
File diff suppressed because it is too large
Load Diff
483
cipher/dsa.c
483
cipher/dsa.c
@ -1,483 +0,0 @@
|
||||
/* dsa.c - DSA signature algorithm
|
||||
* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "util.h"
|
||||
#include "mpi.h"
|
||||
#include "cipher.h"
|
||||
#include "dsa.h"
|
||||
|
||||
typedef struct {
|
||||
MPI p; /* prime */
|
||||
MPI q; /* group order */
|
||||
MPI g; /* group generator */
|
||||
MPI y; /* g^x mod p */
|
||||
} DSA_public_key;
|
||||
|
||||
|
||||
typedef struct {
|
||||
MPI p; /* prime */
|
||||
MPI q; /* group order */
|
||||
MPI g; /* group generator */
|
||||
MPI y; /* g^x mod p */
|
||||
MPI x; /* secret exponent */
|
||||
} DSA_secret_key;
|
||||
|
||||
|
||||
static MPI gen_k( MPI q );
|
||||
static void test_keys( DSA_secret_key *sk, unsigned qbits );
|
||||
static int check_secret_key( DSA_secret_key *sk );
|
||||
static void generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors );
|
||||
static void sign(MPI r, MPI s, MPI input, DSA_secret_key *skey);
|
||||
static int verify(MPI r, MPI s, MPI input, DSA_public_key *pkey);
|
||||
|
||||
|
||||
static void (*progress_cb) ( void *, int );
|
||||
static void *progress_cb_data;
|
||||
|
||||
void
|
||||
register_pk_dsa_progress ( void (*cb)( void *, int), void *cb_data )
|
||||
{
|
||||
progress_cb = cb;
|
||||
progress_cb_data = cb_data;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
progress( int c )
|
||||
{
|
||||
if ( progress_cb )
|
||||
progress_cb ( progress_cb_data, c );
|
||||
else
|
||||
fputc( c, stderr );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Generate a random secret exponent k less than q
|
||||
*/
|
||||
static MPI
|
||||
gen_k( MPI q )
|
||||
{
|
||||
MPI k = mpi_alloc_secure( mpi_get_nlimbs(q) );
|
||||
unsigned int nbits = mpi_get_nbits(q);
|
||||
unsigned int nbytes = (nbits+7)/8;
|
||||
char *rndbuf = NULL;
|
||||
|
||||
if( DBG_CIPHER )
|
||||
log_debug("choosing a random k ");
|
||||
for(;;) {
|
||||
if( DBG_CIPHER )
|
||||
progress('.');
|
||||
|
||||
if( !rndbuf || nbits < 32 ) {
|
||||
m_free(rndbuf);
|
||||
rndbuf = get_random_bits( nbits, 1, 1 );
|
||||
}
|
||||
else { /* change only some of the higher bits */
|
||||
/* we could imporove this by directly requesting more memory
|
||||
* at the first call to get_random_bits() and use this the here
|
||||
* maybe it is easier to do this directly in random.c */
|
||||
char *pp = get_random_bits( 32, 1, 1 );
|
||||
memcpy( rndbuf,pp, 4 );
|
||||
m_free(pp);
|
||||
}
|
||||
mpi_set_buffer( k, rndbuf, nbytes, 0 );
|
||||
if( mpi_test_bit( k, nbits-1 ) )
|
||||
mpi_set_highbit( k, nbits-1 );
|
||||
else {
|
||||
mpi_set_highbit( k, nbits-1 );
|
||||
mpi_clear_bit( k, nbits-1 );
|
||||
}
|
||||
|
||||
if( !(mpi_cmp( k, q ) < 0) ) { /* check: k < q */
|
||||
if( DBG_CIPHER )
|
||||
progress('+');
|
||||
continue; /* no */
|
||||
}
|
||||
if( !(mpi_cmp_ui( k, 0 ) > 0) ) { /* check: k > 0 */
|
||||
if( DBG_CIPHER )
|
||||
progress('-');
|
||||
continue; /* no */
|
||||
}
|
||||
break; /* okay */
|
||||
}
|
||||
m_free(rndbuf);
|
||||
if( DBG_CIPHER )
|
||||
progress('\n');
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_keys( DSA_secret_key *sk, unsigned qbits )
|
||||
{
|
||||
DSA_public_key pk;
|
||||
MPI test = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
|
||||
MPI out1_a = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
|
||||
MPI out1_b = mpi_alloc( qbits / BITS_PER_MPI_LIMB );
|
||||
|
||||
pk.p = sk->p;
|
||||
pk.q = sk->q;
|
||||
pk.g = sk->g;
|
||||
pk.y = sk->y;
|
||||
/*mpi_set_bytes( test, qbits, get_random_byte, 0 );*/
|
||||
{ char *p = get_random_bits( qbits, 0, 0 );
|
||||
mpi_set_buffer( test, p, (qbits+7)/8, 0 );
|
||||
m_free(p);
|
||||
}
|
||||
|
||||
sign( out1_a, out1_b, test, sk );
|
||||
if( !verify( out1_a, out1_b, test, &pk ) )
|
||||
log_fatal("DSA:: sign, verify failed\n");
|
||||
|
||||
mpi_free( test );
|
||||
mpi_free( out1_a );
|
||||
mpi_free( out1_b );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Generate a DSA key pair with a key of size NBITS
|
||||
* Returns: 2 structures filled with all needed values
|
||||
* and an array with the n-1 factors of (p-1)
|
||||
*/
|
||||
static void
|
||||
generate( DSA_secret_key *sk, unsigned nbits, MPI **ret_factors )
|
||||
{
|
||||
MPI p; /* the prime */
|
||||
MPI q; /* the 160 bit prime factor */
|
||||
MPI g; /* the generator */
|
||||
MPI y; /* g^x mod p */
|
||||
MPI x; /* the secret exponent */
|
||||
MPI h, e; /* helper */
|
||||
unsigned qbits;
|
||||
byte *rndbuf;
|
||||
|
||||
assert( nbits >= 512 && nbits <= 1024 );
|
||||
|
||||
qbits = 160;
|
||||
p = generate_elg_prime( 1, nbits, qbits, NULL, ret_factors );
|
||||
/* get q out of factors */
|
||||
q = mpi_copy((*ret_factors)[0]);
|
||||
if( mpi_get_nbits(q) != qbits )
|
||||
BUG();
|
||||
|
||||
/* find a generator g (h and e are helpers)*/
|
||||
/* e = (p-1)/q */
|
||||
e = mpi_alloc( mpi_get_nlimbs(p) );
|
||||
mpi_sub_ui( e, p, 1 );
|
||||
mpi_fdiv_q( e, e, q );
|
||||
g = mpi_alloc( mpi_get_nlimbs(p) );
|
||||
h = mpi_alloc_set_ui( 1 ); /* we start with 2 */
|
||||
do {
|
||||
mpi_add_ui( h, h, 1 );
|
||||
/* g = h^e mod p */
|
||||
mpi_powm( g, h, e, p );
|
||||
} while( !mpi_cmp_ui( g, 1 ) ); /* continue until g != 1 */
|
||||
|
||||
/* select a random number which has these properties:
|
||||
* 0 < x < q-1
|
||||
* This must be a very good random number because this
|
||||
* is the secret part. */
|
||||
if( DBG_CIPHER )
|
||||
log_debug("choosing a random x ");
|
||||
assert( qbits >= 160 );
|
||||
x = mpi_alloc_secure( mpi_get_nlimbs(q) );
|
||||
mpi_sub_ui( h, q, 1 ); /* put q-1 into h */
|
||||
rndbuf = NULL;
|
||||
do {
|
||||
if( DBG_CIPHER )
|
||||
progress('.');
|
||||
if( !rndbuf )
|
||||
rndbuf = get_random_bits( qbits, 2, 1 );
|
||||
else { /* change only some of the higher bits (= 2 bytes)*/
|
||||
char *r = get_random_bits( 16, 2, 1 );
|
||||
memcpy(rndbuf, r, 16/8 );
|
||||
m_free(r);
|
||||
}
|
||||
mpi_set_buffer( x, rndbuf, (qbits+7)/8, 0 );
|
||||
mpi_clear_highbit( x, qbits+1 );
|
||||
} while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, h )<0 ) );
|
||||
m_free(rndbuf);
|
||||
mpi_free( e );
|
||||
mpi_free( h );
|
||||
|
||||
/* y = g^x mod p */
|
||||
y = mpi_alloc( mpi_get_nlimbs(p) );
|
||||
mpi_powm( y, g, x, p );
|
||||
|
||||
if( DBG_CIPHER ) {
|
||||
progress('\n');
|
||||
log_mpidump("dsa p= ", p );
|
||||
log_mpidump("dsa q= ", q );
|
||||
log_mpidump("dsa g= ", g );
|
||||
log_mpidump("dsa y= ", y );
|
||||
log_mpidump("dsa x= ", x );
|
||||
}
|
||||
|
||||
/* copy the stuff to the key structures */
|
||||
sk->p = p;
|
||||
sk->q = q;
|
||||
sk->g = g;
|
||||
sk->y = y;
|
||||
sk->x = x;
|
||||
|
||||
/* now we can test our keys (this should never fail!) */
|
||||
test_keys( sk, qbits );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Test whether the secret key is valid.
|
||||
* Returns: if this is a valid key.
|
||||
*/
|
||||
static int
|
||||
check_secret_key( DSA_secret_key *sk )
|
||||
{
|
||||
int rc;
|
||||
MPI y = mpi_alloc( mpi_get_nlimbs(sk->y) );
|
||||
|
||||
mpi_powm( y, sk->g, sk->x, sk->p );
|
||||
rc = !mpi_cmp( y, sk->y );
|
||||
mpi_free( y );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Make a DSA signature from HASH and put it into r and s.
|
||||
*
|
||||
* Without generating the k this function runs in
|
||||
* about 26ms on a 300 Mhz Mobile Pentium
|
||||
*/
|
||||
|
||||
static void
|
||||
sign(MPI r, MPI s, MPI hash, DSA_secret_key *skey )
|
||||
{
|
||||
MPI k;
|
||||
MPI kinv;
|
||||
MPI tmp;
|
||||
|
||||
/* select a random k with 0 < k < q */
|
||||
k = gen_k( skey->q );
|
||||
|
||||
/* r = (a^k mod p) mod q */
|
||||
mpi_powm( r, skey->g, k, skey->p );
|
||||
mpi_fdiv_r( r, r, skey->q );
|
||||
|
||||
/* kinv = k^(-1) mod q */
|
||||
kinv = mpi_alloc( mpi_get_nlimbs(k) );
|
||||
mpi_invm(kinv, k, skey->q );
|
||||
|
||||
/* s = (kinv * ( hash + x * r)) mod q */
|
||||
tmp = mpi_alloc( mpi_get_nlimbs(skey->p) );
|
||||
mpi_mul( tmp, skey->x, r );
|
||||
mpi_add( tmp, tmp, hash );
|
||||
mpi_mulm( s , kinv, tmp, skey->q );
|
||||
|
||||
mpi_free(k);
|
||||
mpi_free(kinv);
|
||||
mpi_free(tmp);
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Returns true if the signature composed from R and S is valid.
|
||||
*
|
||||
* Without the checks this function runs in
|
||||
* about 31ms on a 300 Mhz Mobile Pentium
|
||||
*/
|
||||
static int
|
||||
verify(MPI r, MPI s, MPI hash, DSA_public_key *pkey )
|
||||
{
|
||||
int rc;
|
||||
MPI w, u1, u2, v;
|
||||
MPI base[3];
|
||||
MPI exp[3];
|
||||
|
||||
|
||||
if( !(mpi_cmp_ui( r, 0 ) > 0 && mpi_cmp( r, pkey->q ) < 0) )
|
||||
return 0; /* assertion 0 < r < q failed */
|
||||
if( !(mpi_cmp_ui( s, 0 ) > 0 && mpi_cmp( s, pkey->q ) < 0) )
|
||||
return 0; /* assertion 0 < s < q failed */
|
||||
|
||||
w = mpi_alloc( mpi_get_nlimbs(pkey->q) );
|
||||
u1 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
|
||||
u2 = mpi_alloc( mpi_get_nlimbs(pkey->q) );
|
||||
v = mpi_alloc( mpi_get_nlimbs(pkey->p) );
|
||||
|
||||
/* w = s^(-1) mod q */
|
||||
mpi_invm( w, s, pkey->q );
|
||||
|
||||
/* u1 = (hash * w) mod q */
|
||||
mpi_mulm( u1, hash, w, pkey->q );
|
||||
|
||||
/* u2 = r * w mod q */
|
||||
mpi_mulm( u2, r, w, pkey->q );
|
||||
|
||||
/* v = g^u1 * y^u2 mod p mod q */
|
||||
base[0] = pkey->g; exp[0] = u1;
|
||||
base[1] = pkey->y; exp[1] = u2;
|
||||
base[2] = NULL; exp[2] = NULL;
|
||||
mpi_mulpowm( v, base, exp, pkey->p );
|
||||
mpi_fdiv_r( v, v, pkey->q );
|
||||
|
||||
rc = !mpi_cmp( v, r );
|
||||
|
||||
mpi_free(w);
|
||||
mpi_free(u1);
|
||||
mpi_free(u2);
|
||||
mpi_free(v);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************
|
||||
************** interface ******************
|
||||
*********************************************/
|
||||
|
||||
int
|
||||
dsa_generate( int algo, unsigned nbits, MPI *skey, MPI **retfactors )
|
||||
{
|
||||
DSA_secret_key sk;
|
||||
|
||||
if( algo != PUBKEY_ALGO_DSA )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
|
||||
generate( &sk, nbits, retfactors );
|
||||
skey[0] = sk.p;
|
||||
skey[1] = sk.q;
|
||||
skey[2] = sk.g;
|
||||
skey[3] = sk.y;
|
||||
skey[4] = sk.x;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
dsa_check_secret_key( int algo, MPI *skey )
|
||||
{
|
||||
DSA_secret_key sk;
|
||||
|
||||
if( algo != PUBKEY_ALGO_DSA )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
if( !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] )
|
||||
return G10ERR_BAD_MPI;
|
||||
|
||||
sk.p = skey[0];
|
||||
sk.q = skey[1];
|
||||
sk.g = skey[2];
|
||||
sk.y = skey[3];
|
||||
sk.x = skey[4];
|
||||
if( !check_secret_key( &sk ) )
|
||||
return G10ERR_BAD_SECKEY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
dsa_sign( int algo, MPI *resarr, MPI data, MPI *skey )
|
||||
{
|
||||
DSA_secret_key sk;
|
||||
|
||||
if( algo != PUBKEY_ALGO_DSA )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
if( !data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] )
|
||||
return G10ERR_BAD_MPI;
|
||||
|
||||
sk.p = skey[0];
|
||||
sk.q = skey[1];
|
||||
sk.g = skey[2];
|
||||
sk.y = skey[3];
|
||||
sk.x = skey[4];
|
||||
resarr[0] = mpi_alloc( mpi_get_nlimbs( sk.p ) );
|
||||
resarr[1] = mpi_alloc( mpi_get_nlimbs( sk.p ) );
|
||||
sign( resarr[0], resarr[1], data, &sk );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dsa_verify( int algo, MPI hash, MPI *data, MPI *pkey,
|
||||
int (*cmp)(void *, MPI), void *opaquev )
|
||||
{
|
||||
DSA_public_key pk;
|
||||
|
||||
if( algo != PUBKEY_ALGO_DSA )
|
||||
return G10ERR_PUBKEY_ALGO;
|
||||
if( !data[0] || !data[1] || !hash
|
||||
|| !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] )
|
||||
return G10ERR_BAD_MPI;
|
||||
|
||||
pk.p = pkey[0];
|
||||
pk.q = pkey[1];
|
||||
pk.g = pkey[2];
|
||||
pk.y = pkey[3];
|
||||
if( !verify( data[0], data[1], hash, &pk ) )
|
||||
return G10ERR_BAD_SIGN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned
|
||||
dsa_get_nbits( int algo, MPI *pkey )
|
||||
{
|
||||
if( algo != PUBKEY_ALGO_DSA )
|
||||
return 0;
|
||||
return mpi_get_nbits( pkey[0] );
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Return some information about the algorithm. We need algo here to
|
||||
* distinguish different flavors of the algorithm.
|
||||
* Returns: A pointer to string describing the algorithm or NULL if
|
||||
* the ALGO is invalid.
|
||||
* Usage: Bit 0 set : allows signing
|
||||
* 1 set : allows encryption
|
||||
*/
|
||||
const char *
|
||||
dsa_get_info( int algo, int *npkey, int *nskey, int *nenc, int *nsig,
|
||||
int *use )
|
||||
{
|
||||
*npkey = 4;
|
||||
*nskey = 5;
|
||||
*nenc = 0;
|
||||
*nsig = 2;
|
||||
|
||||
switch( algo ) {
|
||||
case PUBKEY_ALGO_DSA: *use = PUBKEY_USAGE_SIG; return "DSA";
|
||||
default: *use = 0; return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user