Page MenuHome GnuPG

No OneTemporary

This document is not UTF8. It was detected as ISO-8859-1 (Latin 1) and converted to UTF8 for display.
diff --git a/PROJECTS b/PROJECTS
index a794148c3..2d89d918d 100644
--- a/PROJECTS
+++ b/PROJECTS
@@ -1,53 +1,51 @@
* Check if an object (a message, detached sign, public key, or whatever)
is signed by definite user, i.e. define user
(userid, or any other unique identification) on command line.
--> NO: Use a script and --status-fd
* Change the internal 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.
* signature verification is done duplicated on import: in import.c and
then in trustdb.c too. Maybe we can use a flag to skip the actual
verification process (this should work if we use the same keyblock,
but I'm not sure how to accomplish that). Another way is to allow
the import of bogus data and let trustdb mark these keys as invalid;
I see an advantage in this that it may help to prevent a DoS on a
keyserver by sending him a lot of bogus signatures which he has
to check - Needs further investigation.
* 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 a special ELF segment?
* Split key support (n-out-of-m)
- * Check Berkeley DB - it is in glibc - any licensing problems?
-
* add an option to re-create a public key from a secret key; we
can do this in trustdb.c:verify_own_keys.
(special tool?)
* rewrite --list-packets or put it into another tool.
* We need a maintenance pass over the trustdb which flags
signatures as expired if the key used to make the signature has
expired. Maybe it is a good idea to store the expiration time
in the key record of the trustdb.
* write a tool to extract selected keys from a file.
* Change the buffering to a mbuf like scheme? Need it for PSST anyway;
see Michael's proposal.
* Work on the library
* 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.
diff --git a/THANKS b/THANKS
index f5435e5c9..8fe47c17d 100644
--- a/THANKS
+++ b/THANKS
@@ -1,101 +1,101 @@
GnuPG was originally written by Werner Koch. Other people contributed by
reporting problems, suggesting various improvements or submitting actual
code. Here is a list of those people. Help me keep it complete and free of
errors.
Anand Kumria wildfire@progsoc.uts.edu.au
Ariel T Glenn ariel@columbia.edu
Bryan Fullerton bryanf@samurai.com
Brian Moore bem@cmc.net
Brian Warner warner@lothar.com
Caskey L. Dickson caskey@technocage.com
Cees van de Griend cees-list@griend.xs4all.nl
Charles Levert charles@comm.polymtl.ca
Christian von Roques roques@pond.sub.org
Christopher Oliver oliver@fritz.traverse.net
Christian Recktenwald chris@citecs.de
Daniel Eisenbud eisenbud@cs.swarthmore.edu
David Ellement ellement@sdd.hp.com
Detlef Lannert lannert@lannert.rz.uni-duesseldorf.de
Dirk Lattermann dlatt@t-online.de
Ed Boraas ecxjo@esperanto.org
Ernst Molitor ernst.molitor@uni-bonn.de
Fabio Coatti cova@felix.unife.it
Felix von Leitner leitner@amdiv.de
Frank Heckenbach heckenb@mi.uni-erlangen.de
Gaël Quéri gqueri@mail.dotcom.fr
Greg Louis glouis@dynamicro.on.ca
Greg Troxel gdt@ir.bbn.com
Gregory Steuck steuck@iname.com
Geoff Keating geoffk@ozemail.com.au
Harald Denker harry@hal.westfalen.de
Hendrik Buschkamp buschkamp@rheumanet.org
Holger Schurig holger@d.om.org
Hugh Daniel hugh@toad.com
Ian McKellar imckellar@harvestroad.com.au
Janusz A. Urbanowicz alex@bofh.torun.pl
James Troup james@nocrew.org
Jean-loup Gailly gzip@prep.ai.mit.edu
Jens Bachem bachem@rrz.uni-koeln.de
Joachim Backes backes@rhrk.uni-kl.de
John A. Martin jam@jamux.com
Johnny Teveßen j.tevessen@gmx.de
Jörg Schilling schilling@fokus.gmd.de
Jun Kuriyama kuriyama@sky.rim.or.jp
Karl Fogel kfogel@guanabana.onshore.com
Karsten Thygesen karthy@kom.auc.dk
Kazu Yamamoto kazu@iijlab.net
Lars Kellogg-Stedman lars@bu.edu
Marco d'Itri md@linux.it
Mark Adler madler@alumni.caltech.edu
Markus Friedl Markus.Friedl@informatik.uni-erlangen.de
Martin Kahlert martin.kahlert@provi.de
Martin Schulte schulte@thp.uni-koeln.de
Matthew Skala mskala@ansuz.sooke.bc.ca
Max Valianskiy maxcom@maxcom.ml.org
Michael Roth mroth@nessie.de
Michael Sobolev mss@despair.transas.com
Nicolas Graner Nicolas.Graner@cri.u-psud.fr
Niklas Hernaeus [Please don't spam him]
Nimrod Zimerman zimerman@forfree.at
N J Doye nic@niss.ac.uk
Oskari Jääskeläinen f33003a@cc.hut.fi
Paul D. Smith psmith@baynetworks.com
Philippe Laliberte arsphl@oeil.qc.ca
Peter Gutmann pgut001@cs.auckland.ac.nz
QingLong qinglong@bolizm.ihep.su
Ralph Gillen gillen@theochem.uni-duesseldorf.de
Rat ratinox@peorth.gweep.net
Reinhard Wobst R.Wobst@ifw-dresden.de
-Rémi Guyomarch rguyomarch@ifn.fr
+Rémi Guyomarch rguyom@mail.dotcom.fr
Reuben Sumner rasumner@wisdom.weizmann.ac.il
Roddy Strachan roddy@satlink.com.au
Roland Rosenfeld roland@spinnaker.rhein.de
Ross Golder rossigee@bigfoot.com
Serge Munhoven munhoven@mema.ucl.ac.be
SL Baur steve@xemacs.org
Stefan Karrmann S.Karrmann@gmx.net
Stefan Keller dres@cs.tu-berlin.de
Steffen Ullrich ccrlphr@xensei.com
Steffen Zahn zahn@berlin.snafu.de
Steven Bakker steven@icoe.att.com
Susanne Schultz schultz@hsp.de
Thiago Jung Bauermann jungmann@cwb.matrix.com.br
Thomas Roessler roessler@guug.de
Tom Spindler dogcow@home.merit.edu
Tom Zerucha tzeruch@ceddec.com
Tomas Fasth tomas.fasth@twinspot.net
Thomas Mikkelsen tbm@image.dk
Ulf Möller 3umoelle@informatik.uni-hamburg.de
Urko Lusa ulusa@lacueva.ddns.org
Walter Koch walterk@dip.de
Werner Koch werner.koch@guug.de
Wim Vandeputte bunbun@reptile.rug.ac.be
nbecker@hns.com
Thanks to the German Unix User Group for providing FTP space,
Martin Hamilton for hosting the mailing list and hsp for
hosting gnupg.org.
Many thanks to my wife Gerlinde for having so much patience with
me while hacking late in the evening.
diff --git a/cipher/ChangeLog b/cipher/ChangeLog
index 52dd247de..34d30af24 100644
--- a/cipher/ChangeLog
+++ b/cipher/ChangeLog
@@ -1,428 +1,435 @@
+Tue May 4 15:47:53 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
+
+ * primegen.c (gen_prime): Readded the Fermat test. Fixed the bug
+ that we didn't correct for step when passing the prime to the
+ Rabin-Miller test which led to bad performance (Stefan Keller).
+ (check_prime): Add a first Fermat test.
+
Sun Apr 18 10:11:28 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* cipher.c (cipher_setiv): Add ivlen arg, changed all callers.
* random.c (randomize_buffer): alway use secure memory because
we can't use m_is_secure() on a statically allocated buffer.
* twofish.c: Replaced some macros by a loop to reduce text size.
* Makefile.am (twofish): No more need for sed editing.
Fri Apr 9 12:26:25 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* cipher.c (cipher_open): Reversed the changes for AUTO_CFB.
* blowfish.c: Dropped the Blowfish 160 mode.
* cipher.c (cipher_open): Ditto.
(setup_cipher_table): Ditto. And removed support of twofish128
Wed Apr 7 20:51:39 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* random.c (get_random_bits): Can now handle requests > POOLSIZE
* cipher.c (cipher_open): Now uses standard CFB for automode if
the blocksize is gt 8 (according to rfc2440).
* twofish.c: Applied Matthew Skala's patches for 256 bit key.
Tue Apr 6 19:58:12 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* random.c (get_random_bits): Can now handle requests > POOLSIZE
* cipher.c (cipher_open): Now uses standard CFB for automode if
the blocksize is gt 8 (according to rfc2440).
Sat Mar 20 11:44:21 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* rndlinux.c (tty_printf) [IS_MODULE]: Removed.
* rndegd.c (gather_random): Some fixes.
Wed Mar 17 13:09:03 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* rndegd.c (do_read): New.
(gather_random): Changed the implementation.
Mon Mar 8 20:47:17 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* dynload.c (DLSYM_NEEDS_UNDERSCORE): Renamed.
Fri Feb 26 17:55:41 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* md.c: Nearly a total rewrote.
Wed Feb 24 11:07:27 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* cipher.c (context): Fixed alignment
* md.c: Ditto.
* rndegd.c: New
Mon Feb 22 20:04:00 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* rndegd.c: New.
Wed Feb 10 17:15:39 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* Makefile.am: Modules are now figured out by configure
* construct.c: New. Generated by configure. Changed all modules
to work with that.
* sha1.h: Removed.
* md5.h: Removed.
* twofish.c: Changed interface to allow Twofish/256
* rndunix.c (start_gatherer): Die on SIGPIPE.
Wed Jan 20 18:59:49 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* rndunix.c (gather_random): Fix to avoid infinite loop.
Sun Jan 17 11:04:33 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* des.c (is_weak_key): Replace system memcmp due to bugs
in SunOS's memcmp.
(des_get_info): Return error on failed selftest.
* twofish.c (twofish_setkey): Return error on failed selftest or
invalid keylength.
* cast5.c (cast_setkey): Ditto.
* blowfish.c (bf_setkey): Return error on failed selftest.
Tue Jan 12 11:17:18 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* random.c (random_is_faked): New.
* tiger.c: Only compile if we have the u64 type
Sat Jan 9 16:02:23 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* rndunix.c (gather_random): check for setuid.
* Makefile.am: Add a way to staically link random modules
Thu Jan 7 18:00:58 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* md.c (md_stop_debug): Do a flush first.
(md_open): size of buffer now depends on the secure parameter
Sun Jan 3 15:28:44 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* rndunix.c (start_gatherer): Fixed stupid ==/= bug
1998-12-31 Geoff Keating <geoffk@ozemail.com.au>
* des.c (is_weak_key): Rewrite loop end condition.
Tue Dec 29 14:41:47 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* random.c: add unistd.h for getpid().
(RAND_MAX): Fallback value for Sun.
Wed Dec 23 17:12:24 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* md.c (md_copy): Reset debug.
Mon Dec 14 21:18:49 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* random.c (read_random_source): Changed the interface to the
random gathering function.
(gather_faked): Use new interface.
* dynload.c (dynload_getfnc_fast_random_poll): Ditto.
(dynload_getfnc_gather_random): Ditto.
* rndlinux.c (gather_random): Ditto.
* rndunix.c (gather_random): Ditto.
Sat Dec 12 18:40:32 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* dynload.c (SYMBOL_VERSION): New to cope with system which needs
underscores.
* rndunix.c: Rewrote large parts
Thu Dec 10 20:15:36 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* dynload.c (load_extension): increased needed verbosity level.
* random.c (fast_random_poll): Fallback to a default fast random
poll function.
(read_random_source): Always use the faked entroy gatherer if no
gather module is available.
* rndlinux.c (fast_poll): Removed.
* rndunix.c (fast_poll): Removed.
Wed Nov 25 12:33:41 1998 Werner Koch (wk@isil.d.shuttle.de)
* rand-*.c: Removed.
* rndlinux.c : New.
* rndunix.c : New.
* random.c : Restructured the interface to the gather modules.
(intialize): Call constructor functions
(read_radnom_source): Moved to here.
* dynload.c (dynload_getfnc_gather_random): New.
(dynload_getfnc_fast_random_poll): New.
(register_internal_cipher_extension): New.
(register_cipher_extension): Support of internal modules.
Sun Nov 8 17:44:36 1998 Werner Koch (wk@isil.d.shuttle.de)
* rand-unix.c (read_random_source): Removed the assert.
Mon Oct 19 18:34:30 1998 me,,, (wk@tobold)
* pubkey.c: Hack to allow us to give some info about RSA keys back.
Thu Oct 15 11:47:57 1998 Werner Koch (wk@isil.d.shuttle.de)
* dynload.c: Support for DLD
Wed Oct 14 12:13:07 1998 Werner Koch (wk@isil.d.shuttle.de)
* rand-unix.c: Now uses names from configure for /dev/random.
1998-10-10 SL Baur <steve@altair.xemacs.org>
* Makefile.am: fix sed -O substitutions to catch -O6, etc.
Tue Oct 6 10:06:32 1998 Werner Koch (wk@isil.d.shuttle.de)
* rand-unix.c (HAVE_GETTIMEOFDAY): Fixed (was ..GETTIMEOFTIME :-)
* rand-dummy.c (HAVE_GETTIMEOFDAY): Ditto.
Mon Sep 28 13:23:09 1998 Werner Koch (wk@isil.d.shuttle.de)
* md.c (md_digest): New.
(md_reset): New.
Wed Sep 23 12:27:02 1998 Werner Koch (wk@isil.d.shuttle.de)
* tiger.c (TIGER_CONTEXT): moved "buf", so that it is 64 bit aligned.
Mon Sep 21 06:22:53 1998 Werner Koch (wk@(none))
* des.c: Some patches from Michael.
Thu Sep 17 19:00:06 1998 Werner Koch (wk@(none))
* des.c : New file from Michael Roth <mroth@nessie.de>
Mon Sep 14 11:10:55 1998 Werner Koch (wk@(none))
* blowfish.c (bf_setkey): Niklas Hernaeus patch to detect weak keys.
Mon Sep 14 09:19:25 1998 Werner Koch (wk@(none))
* dynload.c (RTLD_NOW): Now defined to 1 if it is undefined.
Mon Sep 7 17:04:33 1998 Werner Koch (wk@(none))
* Makefile.am: Fixes to allow a different build directory
Thu Aug 6 17:25:38 1998 Werner Koch,mobil,,, (wk@tobold)
* random.c (get_random_byte): Removed and changed all callers
to use get_random_bits()
Mon Jul 27 10:30:22 1998 Werner Koch (wk@(none))
* cipher.c : Support for other blocksizes
(cipher_get_blocksize): New.
* twofish.c: New.
* Makefile.am: Add twofish module.
Mon Jul 13 21:30:52 1998 Werner Koch (wk@isil.d.shuttle.de)
* random.c (read_pool): Simple alloc if secure_alloc is not set.
(get_random_bits): Ditto.
Thu Jul 9 13:01:14 1998 Werner Koch (wk@isil.d.shuttle.de)
* dynload.c (load_extension): Function now nbails out if
the program is run setuid.
Wed Jul 8 18:58:23 1998 Werner Koch (wk@isil.d.shuttle.de)
* rmd160.c (rmd160_hash_buffer): New.
Thu Jul 2 10:50:30 1998 Werner Koch (wk@isil.d.shuttle.de)
* cipher.c (cipher_open): algos >=100 use standard CFB
Thu Jun 25 11:18:25 1998 Werner Koch (wk@isil.d.shuttle.de)
* Makefile.am: Support for extensions
Thu Jun 18 12:09:38 1998 Werner Koch (wk@isil.d.shuttle.de)
* random.c (mix_pool): simpler handling for level 0
Mon Jun 15 14:40:48 1998 Werner Koch (wk@isil.d.shuttle.de)
* tiger.c: Removed from dist, will reappear as dynload module
Sat Jun 13 14:16:57 1998 Werner Koch (wk@isil.d.shuttle.de)
* pubkey.c: Major changes to allow extensions. Changed the inteface
of all public key ciphers and added the ability to load extensions
on demand.
* misc.c: Removed.
Wed Jun 10 07:52:08 1998 Werner Koch,mobil,,, (wk@tobold)
* dynload.c: New.
* cipher.c: Major changes to allow extensions.
Mon Jun 8 22:43:00 1998 Werner Koch (wk@isil.d.shuttle.de)
* cipher.c: Major internal chnages to support extensions.
* blowfish.c (blowfish_get_info): New and made all internal
functions static, changed heder.
* cast5.c (cast5_get_info): Likewise.
Mon Jun 8 12:27:52 1998 Werner Koch (wk@isil.d.shuttle.de)
* tiger.c (transform): Fix for big endian
* cipher.c (do_cfb_decrypt): Big endian fix.
Fri May 22 07:30:39 1998 Werner Koch (wk@isil.d.shuttle.de)
* md.c (md_get_oid): Add a new one for TIGER.
Thu May 21 13:24:52 1998 Werner Koch (wk@isil.d.shuttle.de)
* cipher.c: Add support for a dummy cipher
Thu May 14 15:40:36 1998 Werner Koch (wk@isil.d.shuttle.de)
* rmd160.c (transform): fixed sigbus - I should better
add Christian von Roques's new implemenation of rmd160_write.
Fri May 8 18:07:44 1998 Werner Koch (wk@isil.d.shuttle.de)
* rand-internal.h, rand-unix.c, rand-w32.c, rand_dummy.c: New
* random.c: Moved system specific functions to rand-****.c
Fri May 8 14:01:17 1998 Werner Koch (wk@isil.d.shuttle.de)
* random.c (fast_random_poll): add call to gethrtime.
Tue May 5 21:28:55 1998 Werner Koch (wk@isil.d.shuttle.de)
* elgamal.c (elg_generate): choosing x was not correct, could
yield 6 bytes which are not from the random pool, tsss, tsss..
Tue May 5 14:09:06 1998 Werner Koch (wk@isil.d.shuttle.de)
* primegen.c (generate_elg_prime): Add arg mode, changed all
callers and implemented mode 1.
Mon Apr 27 14:41:58 1998 Werner Koch (wk@isil.d.shuttle.de)
* cipher.c (cipher_get_keylen): New.
Sun Apr 26 14:44:52 1998 Werner Koch (wk@isil.d.shuttle.de)
* tiger.c, tiger.h: New.
Wed Apr 8 14:57:11 1998 Werner Koch (wk@isil.d.shuttle.de)
* misc.c (check_pubkey_algo2): New.
Tue Apr 7 18:46:49 1998 Werner Koch (wk@isil.d.shuttle.de)
* cipher.c: New
* misc.c (check_cipher_algo): Moved to cipher.c
* cast5.c: Moved many functions to cipher.c
* blowfish.c: Likewise.
Sat Apr 4 19:52:08 1998 Werner Koch (wk@isil.d.shuttle.de)
* cast5.c: Implemented and tested.
Wed Apr 1 16:38:27 1998 Werner Koch (wk@isil.d.shuttle.de)
* elgamal.c (elg_generate): Faster generation of x in some cases.
Thu Mar 19 13:54:48 1998 Werner Koch (wk@isil.d.shuttle.de)
* blowfish.c (blowfish_decode_cfb): changed XOR operation
(blowfish_encode_cfb): Ditto.
Thu Mar 12 14:04:05 1998 Werner Koch (wk@isil.d.shuttle.de)
* sha1.c (transform): Rewrote
* blowfish.c (encrypt): Unrolled for rounds == 16
(decrypt): Ditto.
Tue Mar 10 16:32:08 1998 Werner Koch (wk@isil.d.shuttle.de)
* rmd160.c (transform): Unrolled the loop.
Tue Mar 10 13:05:14 1998 Werner Koch (wk@isil.d.shuttle.de)
* random.c (read_pool): Add pool_balance stuff.
(get_random_bits): New.
* elgamal.c (elg_generate): Now uses get_random_bits to generate x.
Tue Mar 10 11:33:51 1998 Werner Koch (wk@isil.d.shuttle.de)
* md.c (md_digest_length): New.
Tue Mar 10 11:27:41 1998 Werner Koch (wk@isil.d.shuttle.de)
* dsa.c (dsa_verify): Works.
Mon Mar 9 12:59:08 1998 Werner Koch (wk@isil.d.shuttle.de)
* dsa.c, dsa.h: Removed some unused code.
Wed Mar 4 10:39:22 1998 Werner Koch (wk@isil.d.shuttle.de)
* md.c (md_open): Add call to fast_random_poll.
blowfish.c (blowfish_setkey): Ditto.
Tue Mar 3 13:32:54 1998 Werner Koch (wk@isil.d.shuttle.de)
* rmd160.c (rmd160_mixblock): New.
* random.c: Restructured to start with a new RNG implementation.
* random.h: New.
Mon Mar 2 19:21:46 1998 Werner Koch (wk@isil.d.shuttle.de)
* gost.c, gost.h: Removed because they did only conatin trash.
Sun Mar 1 16:42:29 1998 Werner Koch (wk@isil.d.shuttle.de)
* random.c (fill_buffer): removed error message if n == -1.
Fri Feb 27 16:39:34 1998 Werner Koch (wk@isil.d.shuttle.de)
* md.c (md_enable): No init if called twice.
Thu Feb 26 07:57:02 1998 Werner Koch (wk@isil.d.shuttle.de)
* primegen.c (generate_elg_prime): Changed the progress printing.
(gen_prime): Ditto.
Tue Feb 24 12:28:42 1998 Werner Koch (wk@isil.d.shuttle.de)
* md5.c, md.5 : Replaced by a modified version of md5.c from
GNU textutils 1.22.
Wed Feb 18 14:08:30 1998 Werner Koch (wk@isil.d.shuttle.de)
* md.c, md.h : New debugging support
Mon Feb 16 10:08:47 1998 Werner Koch (wk@isil.d.shuttle.de)
* misc.c (cipher_algo_to_string): New
(pubkey_algo_to_string): New.
(digest_algo_to_string): New.
diff --git a/cipher/primegen.c b/cipher/primegen.c
index c7b5b757d..9019e2839 100644
--- a/cipher/primegen.c
+++ b/cipher/primegen.c
@@ -1,562 +1,555 @@
/* primegen.c - prime number generator
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* ***********************************************************************
* The algorithm used to generate practically save primes is due to
* Lim and Lee as described in the CRYPTO '97 proceedings (ISBN3540633847)
* page 260.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "util.h"
#include "mpi.h"
#include "cipher.h"
static int no_of_small_prime_numbers;
static MPI gen_prime( unsigned nbits, int mode, int randomlevel );
-static int check_prime( MPI prime );
+static int check_prime( MPI prime, MPI val_2 );
static int is_prime( MPI n, int steps, int *count );
static void m_out_of_n( char *array, int m, int n );
/****************
* Generate a prime number (stored in secure memory)
*/
MPI
generate_secret_prime( unsigned nbits )
{
MPI prime;
prime = gen_prime( nbits, 1, 2 );
fputc('\n', stderr);
return prime;
}
MPI
generate_public_prime( unsigned nbits )
{
MPI prime;
prime = gen_prime( nbits, 0, 2 );
fputc('\n', stderr);
return prime;
}
/****************
* We do not need to use the strongest RNG because we gain no extra
* security from it - The prime number is public and we could also
* offer the factors for those who are willing to check that it is
* indeed a strong prime.
*
* mode 0: Standard
* 1: Make sure that at least one factor is of size qbits.
*/
MPI
generate_elg_prime( int mode, unsigned pbits, unsigned qbits,
MPI g, MPI **ret_factors )
{
int n; /* number of factors */
int m; /* number of primes in pool */
unsigned fbits; /* length of prime factors */
MPI *factors; /* current factors */
MPI *pool; /* pool of primes */
MPI q; /* first prime factor (variable)*/
MPI prime; /* prime test value */
MPI q_factor; /* used for mode 1 */
byte *perms = NULL;
int i, j;
int count1, count2;
unsigned nprime;
unsigned req_qbits = qbits; /* the requested q bits size */
+ MPI val_2 = mpi_alloc_set_ui( 2 );
/* find number of needed prime factors */
for(n=1; (pbits - qbits - 1) / n >= qbits; n++ )
;
n--;
if( !n || (mode==1 && n < 2) )
log_fatal("can't gen prime with pbits=%u qbits=%u\n", pbits, qbits );
if( mode == 1 ) {
n--;
fbits = (pbits - 2*req_qbits -1) / n;
qbits = pbits - req_qbits - n*fbits;
}
else {
fbits = (pbits - req_qbits -1) / n;
qbits = pbits - n*fbits;
}
if( DBG_CIPHER )
log_debug("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n",
pbits, req_qbits, qbits, fbits, n );
prime = mpi_alloc( (pbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB );
q = gen_prime( qbits, 0, 1 );
q_factor = mode==1? gen_prime( req_qbits, 0, 1 ) : NULL;
/* allocate an array to hold the factors + 2 for later usage */
factors = m_alloc_clear( (n+2) * sizeof *factors );
/* make a pool of 3n+5 primes (this is an arbitrary value) */
m = n*3+5;
if( mode == 1 )
m += 5; /* need some more for DSA */
if( m < 25 )
m = 25;
pool = m_alloc_clear( m * sizeof *pool );
/* permutate over the pool of primes */
count1=count2=0;
do {
next_try:
if( !perms ) {
/* allocate new primes */
for(i=0; i < m; i++ ) {
mpi_free(pool[i]);
pool[i] = NULL;
}
/* init m_out_of_n() */
perms = m_alloc_clear( m );
for(i=0; i < n; i++ ) {
perms[i] = 1;
pool[i] = gen_prime( fbits, 0, 1 );
factors[i] = pool[i];
}
}
else {
m_out_of_n( perms, n, m );
for(i=j=0; i < m && j < n ; i++ )
if( perms[i] ) {
if( !pool[i] )
pool[i] = gen_prime( fbits, 0, 1 );
factors[j++] = pool[i];
}
if( i == n ) {
m_free(perms); perms = NULL;
fputc('!', stderr);
goto next_try; /* allocate new primes */
}
}
mpi_set( prime, q );
mpi_mul_ui( prime, prime, 2 );
if( mode == 1 )
mpi_mul( prime, prime, q_factor );
for(i=0; i < n; i++ )
mpi_mul( prime, prime, factors[i] );
mpi_add_ui( prime, prime, 1 );
nprime = mpi_get_nbits(prime);
if( nprime < pbits ) {
if( ++count1 > 20 ) {
count1 = 0;
qbits++;
fputc('>', stderr);
q = gen_prime( qbits, 0, 1 );
goto next_try;
}
}
else
count1 = 0;
if( nprime > pbits ) {
if( ++count2 > 20 ) {
count2 = 0;
qbits--;
fputc('<', stderr);
q = gen_prime( qbits, 0, 1 );
goto next_try;
}
}
else
count2 = 0;
- } while( !(nprime == pbits && check_prime( prime )) );
+ } while( !(nprime == pbits && check_prime( prime, val_2 )) );
if( DBG_CIPHER ) {
putc('\n', stderr);
log_mpidump( "prime : ", prime );
log_mpidump( "factor q: ", q );
if( mode == 1 )
log_mpidump( "factor q0: ", q_factor );
for(i=0; i < n; i++ )
log_mpidump( "factor pi: ", factors[i] );
log_debug("bit sizes: prime=%u, q=%u", mpi_get_nbits(prime), mpi_get_nbits(q) );
if( mode == 1 )
fprintf(stderr, ", q0=%u", mpi_get_nbits(q_factor) );
for(i=0; i < n; i++ )
fprintf(stderr, ", p%d=%u", i, mpi_get_nbits(factors[i]) );
putc('\n', stderr);
}
if( ret_factors ) { /* caller wants the factors */
*ret_factors = m_alloc_clear( (n+2) * sizeof **ret_factors);
if( mode == 1 ) {
i = 0;
(*ret_factors)[i++] = mpi_copy( q_factor );
for(; i <= n; i++ )
(*ret_factors)[i] = mpi_copy( factors[i] );
}
else {
for(; i < n; i++ )
(*ret_factors)[i] = mpi_copy( factors[i] );
}
}
if( g ) { /* create a generator (start with 3)*/
MPI tmp = mpi_alloc( mpi_get_nlimbs(prime) );
MPI b = mpi_alloc( mpi_get_nlimbs(prime) );
MPI pmin1 = mpi_alloc( mpi_get_nlimbs(prime) );
if( mode == 1 )
BUG(); /* not yet implemented */
factors[n] = q;
factors[n+1] = mpi_alloc_set_ui(2);
mpi_sub_ui( pmin1, prime, 1 );
mpi_set_ui(g,2);
do {
mpi_add_ui(g, g, 1);
if( DBG_CIPHER ) {
log_debug("checking g: ");
mpi_print( stderr, g, 1 );
}
else
fputc('^', stderr);
for(i=0; i < n+2; i++ ) {
/*fputc('~', stderr);*/
mpi_fdiv_q(tmp, pmin1, factors[i] );
/* (no mpi_pow(), but it is okay to use this with mod prime) */
mpi_powm(b, g, tmp, prime );
if( !mpi_cmp_ui(b, 1) )
break;
}
if( DBG_CIPHER )
fputc('\n', stderr);
} while( i < n+2 );
mpi_free(factors[n+1]);
mpi_free(tmp);
mpi_free(b);
mpi_free(pmin1);
}
if( !DBG_CIPHER )
putc('\n', stderr);
m_free( factors ); /* (factors are shallow copies) */
for(i=0; i < m; i++ )
mpi_free( pool[i] );
m_free( pool );
m_free(perms);
+ mpi_free(val_2);
return prime;
}
static MPI
gen_prime( unsigned nbits, int secret, int randomlevel )
{
unsigned nlimbs;
- MPI prime, val_2, val_3, result;
+ MPI prime, ptest, pminus1, val_2, val_3, result;
int i;
unsigned x, step;
unsigned count1, count2;
int *mods;
if( 0 && DBG_CIPHER )
log_debug("generate a prime of %u bits ", nbits );
if( !no_of_small_prime_numbers ) {
for(i=0; small_prime_numbers[i]; i++ )
no_of_small_prime_numbers++;
}
mods = m_alloc( no_of_small_prime_numbers * sizeof *mods );
/* make nbits fit into MPI implementation */
nlimbs = (nbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB;
- val_2 = mpi_alloc( nlimbs );
- mpi_set_ui(val_2, 2);
- val_3 = mpi_alloc( nlimbs );
- mpi_set_ui(val_3, 3);
- result = mpi_alloc( nlimbs );
+ val_2 = mpi_alloc_set_ui( 2 );
+ val_3 = mpi_alloc_set_ui( 3);
prime = secret? mpi_alloc_secure( nlimbs ): mpi_alloc( nlimbs );
+ result = mpi_alloc_like( prime );
+ pminus1= mpi_alloc_like( prime );
+ ptest = mpi_alloc_like( prime );
count1 = count2 = 0;
- /* enter (endless) loop */
- for(;;) {
+ for(;;) { /* try forvever */
int dotcount=0;
/* generate a random number */
- /*mpi_set_bytes( prime, nbits, get_random_byte, randomlevel );*/
{ char *p = get_random_bits( nbits, randomlevel, secret );
mpi_set_buffer( prime, p, (nbits+7)/8, 0 );
m_free(p);
}
/* set high order bit to 1, set low order bit to 1 */
mpi_set_highbit( prime, nbits-1 );
mpi_set_bit( prime, 0 );
/* calculate all remainders */
for(i=0; (x = small_prime_numbers[i]); i++ )
mods[i] = mpi_fdiv_r_ui(NULL, prime, x);
+ /* now try some primes starting with prime */
for(step=0; step < 20000; step += 2 ) {
/* check against all the small primes we have in mods */
count1++;
for(i=0; (x = small_prime_numbers[i]); i++ ) {
while( mods[i] + step >= x )
mods[i] -= x;
if( !(mods[i] + step) )
break;
}
if( x )
- continue; /* found a multiple of a already known prime */
+ continue; /* found a multiple of an already known prime */
- mpi_add_ui( prime, prime, step );
+ mpi_add_ui( ptest, prime, step );
- #if 0
- /* do a Fermat test */
+ /* do a faster Fermat test */
count2++;
- mpi_powm( result, val_2, prime, prime );
- if( mpi_cmp_ui(result, 2) )
- continue; /* stepping (fermat test failed) */
- fputc('+', stderr);
- #endif
-
- /* perform stronger tests */
- if( is_prime(prime, 5, &count2 ) ) {
- if( !mpi_test_bit( prime, nbits-1 ) ) {
- if( 0 && DBG_CIPHER ) {
+ mpi_sub_ui( pminus1, ptest, 1);
+ mpi_powm( result, val_2, pminus1, ptest );
+ if( !mpi_cmp_ui( result, 1 ) ) { /* not composite */
+ /* perform stronger tests */
+ if( is_prime(ptest, 5, &count2 ) ) {
+ if( !mpi_test_bit( ptest, nbits-1 ) ) {
fputc('\n', stderr);
log_debug("overflow in prime generation\n");
- break; /* step loop, cont with a new prime */
+ break; /* step loop, continue with a new prime */
}
- }
- if( 0 && DBG_CIPHER ) {
- log_debug("performed %u simple and %u stronger tests\n",
- count1, count2 );
- log_mpidump("found prime: ", prime );
+ mpi_free(val_2);
+ mpi_free(val_3);
+ mpi_free(result);
+ mpi_free(pminus1);
+ mpi_free(prime);
+ m_free(mods);
+ return ptest;
}
-
- mpi_free(val_2);
- mpi_free(val_3);
- mpi_free(result);
- m_free(mods);
- return prime;
}
if( ++dotcount == 10 ) {
fputc('.', stderr);
dotcount = 0;
}
}
fputc(':', stderr); /* restart with a new random value */
}
}
/****************
* Returns: true if this may be a prime
*/
static int
-check_prime( MPI prime )
+check_prime( MPI prime, MPI val_2 )
{
int i;
unsigned x;
int count=0;
/* check against small primes */
for(i=0; (x = small_prime_numbers[i]); i++ ) {
if( mpi_divisible_ui( prime, x ) )
return 0;
}
- #if 0
- result = mpi_alloc( mpi_get_nlimbs(prime) );
- val_2 = mpi_alloc_set_ui( 2 );
- mpi_powm( result, val_2, prime, prime );
- if( mpi_cmp_ui(result, 2) ) {
- mpi_free(result);
- mpi_free(val_2);
- return 0;
+ /* a quick fermat test */
+ {
+ MPI result = mpi_alloc_like( prime );
+ MPI pminus1 = mpi_alloc_like( prime );
+ mpi_sub_ui( pminus1, prime, 1);
+ mpi_powm( result, val_2, pminus1, prime );
+ mpi_free( pminus1 );
+ if( mpi_cmp_ui( result, 1 ) ) { /* if composite */
+ mpi_free( result );
+ fputc('.', stderr);
+ return 0;
+ }
+ mpi_free( result );
}
- mpi_free(result);
- mpi_free(val_2);
- fputc('+', stderr);
- #endif
/* perform stronger tests */
if( is_prime(prime, 5, &count ) )
return 1; /* is probably a prime */
fputc('.', stderr);
return 0;
}
/****************
* Return true if n is probably a prime
*/
static int
is_prime( MPI n, int steps, int *count )
{
MPI x = mpi_alloc( mpi_get_nlimbs( n ) );
MPI y = mpi_alloc( mpi_get_nlimbs( n ) );
MPI z = mpi_alloc( mpi_get_nlimbs( n ) );
MPI nminus1 = mpi_alloc( mpi_get_nlimbs( n ) );
MPI a2 = mpi_alloc_set_ui( 2 );
MPI q;
unsigned i, j, k;
int rc = 0;
unsigned nbits = mpi_get_nbits( n );
mpi_sub_ui( nminus1, n, 1 );
/* find q and k, so that n = 1 + 2^k * q */
q = mpi_copy( nminus1 );
k = mpi_trailing_zeros( q );
mpi_tdiv_q_2exp(q, q, k);
for(i=0 ; i < steps; i++ ) {
++*count;
if( !i ) {
mpi_set_ui( x, 2 );
}
else {
/*mpi_set_bytes( x, nbits-1, get_random_byte, 0 );*/
{ char *p = get_random_bits( nbits, 0, 0 );
mpi_set_buffer( x, p, (nbits+7)/8, 0 );
m_free(p);
}
/* make sure that the number is smaller than the prime
* and keep the randomness of the high bit */
if( mpi_test_bit( x, nbits-2 ) ) {
mpi_set_highbit( x, nbits-2 ); /* clear all higher bits */
}
else {
mpi_set_highbit( x, nbits-2 );
mpi_clear_bit( x, nbits-2 );
}
assert( mpi_cmp( x, nminus1 ) < 0 && mpi_cmp_ui( x, 1 ) > 0 );
}
mpi_powm( y, x, q, n);
if( mpi_cmp_ui(y, 1) && mpi_cmp( y, nminus1 ) ) {
for( j=1; j < k && mpi_cmp( y, nminus1 ); j++ ) {
mpi_powm(y, y, a2, n);
if( !mpi_cmp_ui( y, 1 ) )
goto leave; /* not a prime */
}
if( mpi_cmp( y, nminus1 ) )
goto leave; /* not a prime */
}
fputc('+', stderr);
}
rc = 1; /* may be a prime */
leave:
mpi_free( x );
mpi_free( y );
mpi_free( z );
mpi_free( nminus1 );
mpi_free( q );
return rc;
}
static void
m_out_of_n( char *array, int m, int n )
{
int i=0, i1=0, j=0, jp=0, j1=0, k1=0, k2=0;
if( !m || m >= n )
return;
if( m == 1 ) { /* special case */
for(i=0; i < n; i++ )
if( array[i] ) {
array[i++] = 0;
if( i >= n )
i = 0;
array[i] = 1;
return;
}
BUG();
}
for(j=1; j < n; j++ ) {
if( array[n-1] == array[n-j-1] )
continue;
j1 = j;
break;
}
if( m & 1 ) { /* m is odd */
if( array[n-1] ) {
if( j1 & 1 ) {
k1 = n - j1;
k2 = k1+2;
if( k2 > n )
k2 = n;
goto leave;
}
goto scan;
}
k2 = n - j1 - 1;
if( k2 == 0 ) {
k1 = i;
k2 = n - j1;
}
else if( array[k2] && array[k2-1] )
k1 = n;
else
k1 = k2 + 1;
}
else { /* m is even */
if( !array[n-1] ) {
k1 = n - j1;
k2 = k1 + 1;
goto leave;
}
if( !(j1 & 1) ) {
k1 = n - j1;
k2 = k1+2;
if( k2 > n )
k2 = n;
goto leave;
}
scan:
jp = n - j1 - 1;
for(i=1; i <= jp; i++ ) {
i1 = jp + 2 - i;
if( array[i1-1] ) {
if( array[i1-2] ) {
k1 = i1 - 1;
k2 = n - j1;
}
else {
k1 = i1 - 1;
k2 = n + 1 - j1;
}
goto leave;
}
}
k1 = 1;
k2 = n + 1 - m;
}
leave:
array[k1-1] = !array[k1-1];
array[k2-1] = !array[k2-1];
}
diff --git a/doc/FAQ b/doc/FAQ
index 97bf94a05..b008f2ce7 100644
--- a/doc/FAQ
+++ b/doc/FAQ
@@ -1,332 +1,333 @@
GNU Privacy Guard -- Frequently Asked Questions
=================================================
This FAQ is partly compiled from messages of the developers mailing list.
Many thanks to Kirk Fort, Brian Warner, ...
Q: How does this whole thing work?
A: To generate a secret/public keypair, run
gpg --gen-key
and choose the default values.
Data that is encrypted with a public key can only be decrypted by the
matching secret key. The secret key is protected by a password, the
public key is not.
So to send your friend a message, you would encrypt your message with his
public key, and he would only be able to decrypt it by having the secret
key and putting in the password to use his secret key.
GNUPG is also useful for signing things. Things that are encrypted with
the secret key can be decrypted with the public key. To sign something, a
hash is taken of the data, and then the hash is in some form encoded with
the secret key. If someone has your public key, they can verify that it
is from you and that it hasn't changed by checking the encoded form of
the hash with the public key.
A keyring is just a large file that stores keys. You have a public keyring
where you store yours and your friend's public keys. You have a secret
keyring that you keep your secret key on, and be very careful with this
secret keyring: Never ever give anyone else access to it and use a *good*
passphrase to protect the data in it.
You can 'conventionally' encrypt something by using the option 'gpg -c'.
It is encrypted using a passphrase, and does not use public and secret
keys. If the person you send the data to knows that passphrase, they can
decrypt it. This is usually most useful for encrypting things to
yourself, although you can encrypt things to your own public key in the
same way. It should be used for communication with partners you know and
where it is easy to exchange the passphrases (e.g. with your boy friend or
your wife). The advantage is that you can change the passphrase from time
to time and decrease the risk, that many old messages may be decrypted by
people who accidently got your passphrase.
You can add and copy keys to and from your keyring with the 'gpg --import'
and 'gpg --export' option. 'gpg --export-secret-keys' will export secret
keys. This is normally not useful, but you can generate the key on one
machine then move it to another machine.
Keys can be signed under the 'gpg --edit-key' option. When you sign a
key, you are saying that you are certain that the key belongs to the
person it says it comes from. You should be very sure that is really
that person: You should verify the key fingerprint
gpg --fingerprint user-id
over phone (if you really know the voice of the other person) or at
a key signing party (which are often held at computer conferences)
or at a meeting of your local GNU/Linux User Group.
Hmm, what else. You may use the option "-o filename" to force output
to this filename (use "-" to force output to stdout). "-r" just lets you
specify the recipient (which public key you encrypt with) on the command
line instead of typing it interactively.
Oh yeah, this is important. By default all data is encrypted in some weird
binary format. If you want to have things appear in ASCII text that is
readable, just add the '-a' option. But the preferred method is to use
a MIME aware mail reader (Mutt, Pine and many more).
There is a small security glitch in the OpenPGP (and therefor GNUPG) system;
to avoid this you should always sign and encrypt a message instead of only
encrypting it.
Q: What is the recommended key size?
A: 1024 bit for DSA signatures; even for plain ElGamal
signatures this is sufficient as the size of the hash
is probably the weakest link if the keysize is larger
than 1024 bits. Encryption keys may have greater sizes,
- but you should than check the fingerprint of this key.
+ but you should than check the fingerprint of this key:
+ "gpg --fingerprint --fingerprint <user ID>".
Q: Why are some signatures with an ELG-E key valid?
A: These are ElGamal Key generated by GNUPG in v3 (rfc1991)
packets. The OpenPGP draft later changed the algorithm
identifier for ElGamal keys which are usable for signatures
and encryption from 16 to 20. GNUPG now uses 20 when it
generates new ElGamal keys but still accept 16 (which is
according to OpenPGP "encryption only") if this key is in
a v3 packet. GNUPG is the only program which had used
these v3 ElGamal keys - so this assumption is quite safe.
Q: Why is PGP 5.x not able to encrypt messages with some keys?
A: PGP Inc refuses to accept ElGamal keys of type 20 even for
encryption. They only support type 16 (which is identical
at least for decryption). To be more inter-operable, GnuPG
(starting with version 0.3.3) now also uses type 16 for the
ElGamal subkey which is created if the default key algorithm
is chosen. You may add an type 16 ElGamal key to your public
key which is easy as your key signatures are still valid.
Q: Why is PGP 5.x not able to verify my messages?
A: PGP 5.x does not accept V4 signatures for data material but
OpenPGP requires generation of V4 signatures for all kind of
data. Use the option "--force-v3-sigs" to generate V3 signatures
for data.
Q: I can't delete an user id because it is already deleted on my
public keyring?
A: Because you can only select from the public key ring, there is
no direct way to do this. However it is not very complicated
to do it anyway. Create a new user id with exactly the same name
and you will see that there are now two identical user ids on the
secret ring. Now select this user id and delete it. Both user
ids will be removed from the secret ring.
Q: How can I encrypt a message so that pgp 2.x is able to decrypt it?
A: You can't do that because pgp 2.x normally uses IDEA which is not
supported by GNUPG because it is patented, but if you have a modified
version of PGP you can try this:
gpg --rfc1991 --cipher-algo 3des ...
Q: How can I conventional encrypt a message, so that PGP can decrypt it?
A: You can't do this for PGP 2. For PGP 5 you should use this:
gpg -c --cipher-algo 3des --compress-algo 1 myfile
You may replace "3des" by "cast5". "blowfish" does not work with
all versions of pgp5. You may also want to put
compress-algo 1
into your ~/.gnupg/options file - this does not affect normal
gnupg operation.
Q: Why does it sometimes take so long to create keys?
A: The problem here is that we need a lot of random bytes and for that
we (on Linux the /dev/random device) must collect some random data.
It is really not easy to fill the Linux internal entropy buffer; I
talked to Ted Ts'o and he commented that the best way to fill the buffer
is to play with your keyboard. Good security has it's price. What I do
is to hit several times on the shift, control, alternate, and capslock
keys, because these keys do not produce output to the screen. This way
you get your keys really fast (it's the same thing pgp2 does).
Another problem might be another program which eats up your random bytes
(a program (look at your daemons) that reads from /dev/[u]random).
Q: And it really takes long when I work on a remote system. Why?
A: Don't do this at all! You should never create keys or even use GnuPG
on a remote system because you normally have no physical control over
your secret keyring (which is in most cases vulnerable to advanced
dictionary attacks) - I strongly encourage everyone to only create keys
on a local computer (a disconnected laptop is probably the best choice)
and if you need it on your connected box (I know: We all do this) be
sure to have a strong password for your account and for your secret key
and trust your Root.
When I check GnuPG on a remote system via ssh (I have no Alpha here ;-)
I have the same problem. It takes a *very* long time to create the
keys, so I use a special option, --quick-random, to generate insecure
keys which are only good for some tests.
Q: How does the whole trust thing work?
A: It works more or less like PGP. The difference is that the trust is
computed at the time it is needed. This is one of the reasons for the
trustdb which holds a list of valid key signatures. If you are not
running in batch mode you will be asked to assign a trust parameter
(ownertrust) to a key.
You can see the validity (calculated trust value) using this command.
gpgm --list-keys --with-colons
If the first field is "pub" or "uid", the second field shows you the trust:
o = Unknown (this key is new to the system)
e = The key has expired
q = Undefined (no value assigned)
n = Don't trust this key at all
m = There is marginal trust in this key
f = The key is full trusted.
u = The key is ultimately trusted; this
is only used for keys for which
the secret key is also available.
The value in the "pub" record is the best one of all "uid" records.
You can get a list of the assigned trust values (how much you trust
the owner to correctly sign another person's key)
gpgm --list-ownertrust
The first field is the fingerprint of the primary key, the second field
is the assigned value:
- = No Ownertrust value yet assigned.
n = Never trust this keyholder to correctly verify others signatures.
m = Have marginal trust in the keyholders capability to sign other keys.
f = Assume that the key holder really knows how to sign keys.
u = No need to trust ourself because we have the secret key.
Keep these values confidential because they express your opinions
about others. PGP stores this information with the keyring thus
it is not a good idea to publish a PGP keyring instead of exporting the
keyring. gnupg stores the trust in the trust-DB so it is okay
to give a gpg keyring away (but we have a --export command too).
Q: What is the difference between options and commands?
A: If you do a "gpg --help", you will get two separate lists. The first is
a list of commands. The second is a list of options. Whenever you run GPG,
you *must* pick exactly one command (**with one exception, see below). You
*may* pick one or more options. The command should, just by convention,
come at the end of the argument list, after all the options. If the
command takes a file (all the basic ones do), the filename comes at the
very end. So the basic way to run gpg is:
gpg [--option something] [--option2] [--option3 something] --command file
Some options take arguments, for example the --output option (which can be
abbreviated -o) is an option that takes a filename. The option's argument
must follow immediately after the option itself, otherwise gpg doesn't know
which option the argument is supposed to go with. As an option, --output and
its filename must come before the command. The --remote-user (-r) option takes
a name or keyid to encrypt the message to, which must come right after the -r
argument. The --encrypt (or -e) command comes after all the options followed
by the file you wish to encrypt. So use
gpg -r alice -o secret.txt -e test.txt
If you write the options out in full, it is easier to read
gpg --remote-user alice --output secret.txt --encrypt test.txt
If you're saving it in a file called ".txt" then you'd probably expect to see
ASCII-armored text in there, so you need to add the --armor (-a) option,
which doesn't take any arguments.
gpg --armor --remote-user alice --output secret.txt --encrypt test.txt
If you imagine square brackets around the optional parts, it becomes a bit
clearer:
gpg [--armor] [--remote-user alice] [--output secret.txt] --encrypt test.txt
The optional parts can be rearranged any way you want.
gpg --output secret.txt --remote-user alice --armor --encrypt test.txt
If your filename begins with a hyphen (e.g. "-a.txt"), gnupg assumes this is
an option and may complain. To avoid this you have either to use
"./-a.txt" or stop the option and command processing with two hyphens:
"-- -a.txt".
** the exception: signing and encrypting at the same time. Use
gpg [--options] --sign --encrypt foo.txt
Q: What kind of output is this: "key C26EE891.298, uid 09FB: ...."?
A: This is the internal representation of an user id in the trustdb.
"C26EE891" is the keyid, "298" is the local id (a record number
in the trustdb) and "09FB" is the last two bytes of a ripe-md-160
hash of the user id for this key.
Q: What is trust, validity and ownertrust?
A: "ownertrust" is used instead of "trust" to make clear that
this is the value you have assigned to a key to express how much you
trust the owner of this key to correctly sign (and so introduce)
other keys. "validity", or calculated trust, is a value which
says how much GnuPG thinks a key is valid (that it really belongs
to the one who claims to be the owner of the key).
For more see the chapter "The Web of Trust" in the
Manual [gpg: Oops: Internal error: manual not found - sorry]
Q: How do I interpret some of the informational outputs?
A: While checking the validity of a key, GnuPG sometimes prints
some information which is prefixed with information about
the checked item.
"key 12345678.3456"
This is about the key with key ID 12345678 and the internal
number 3456, which is the record number of the so called
directory record in the trustdb.
"uid 12345678.3456/ACDE"
This is about the user ID for the same key. To identify the
user ID the last two bytes of a ripe-md-160 over the user ID
ring is printed.
"sig 12345678.3456/ACDE/9A8B7C6D"
This is about the signature with key ID 9A8B7C6D for the
above key and user ID, if it is a signature which is direct
on a key, the user ID part is empty (..//..).
Q: How do I sign a patch file?
A: Use "gpg --clearsign --not-dash-escaped ...".
The problem with --clearsign is that all lines starting with a dash are
quoted with "- "; obviously diff produces many of lines starting with a
dash and these are then quoted and that is not good for patch ;-). To
use a patch file without removing the cleartext signature, the special
option --not-dash-escaped may be used to suppress generation of these
escape sequences. You should not mail such a patch because spaces and
line endings are also subject to the signature and a mailer may not
preserve these. If you want to mail a file you can simply sign it
using your MUA.
Q: Where is the "encrypt-to-self" option?
A: Use "--encrypt-to your_keyid". You can use more than one
of these options. To temporary override the use of this additional
keys, you can use the option "--no-encrypt-to".
Q: How can I get rid of the Version and Comment headers in
armored messages?
A: Use "--no-version --comment ''". Note that the left over blank line
is required by the protocol.
Q: What does the "You are using the xxxx character set." mean?
A: This note is printed when UTF8 mapping has to be done. Make sure that
the displayed charset is the one you have activated on your system
"iso-8859-1" is the most used one, so this is the default. You can
change the charset with the option "--charset". It is important that
you active characterset matches the one displayed - if not, restrict
yourself to plain 7 bit ASCII and no mapping has to be done.
diff --git a/doc/gpg.1pod b/doc/gpg.1pod
index 9ec4d2ef4..9e8abc44b 100644
--- a/doc/gpg.1pod
+++ b/doc/gpg.1pod
@@ -1,582 +1,584 @@
=head1 NAME
gpg - GNU Privacy Guard
=head1 SYNOPSIS
B<gpg> [--homedir name] [--options file] [options] command [args]
=head1 DESCRIPTION
B<gpg> is the main program for the GnuPG system.
=head1 COMMANDS
B<gpg> recognizes these commands:
B<-s>, B<--sign>
Make a signature. This option may be combined
with B<--encrypt>.
B<--clearsign>
Make a clear text signature.
B<-b>, B<--detach-sign>
Make a detached signature.
B<-e>, B<--encrypt>
Encrypt data. This option may be combined with B<--sign>.
B<-c>, B<--symmetric>
Encrypt with symmetric cipher only
This command asks for a passphrase.
B<--store>
Store only (make a simple RFC1991 packet).
B<--decrypt> [I<file>]
Decrypt file (or stdin if no file is specified) and
write it to stdout (or the file specified with
B<--output>). If the decrypted file is signed, the
signature is also verified. This command differs
from the default operation, as it never writes to the
filename which is included in the file and it
rejects files which don't begin with an encrypted
message.
B<--verify> [[I<sigfile>] {I<signed-files>}]
Assume that I<sigfile> is a signature and verify it
without generating any output. With no arguments,
the signature packet is read from stdin (it may be a
detached signature when not used in batch mode). If
only a sigfile is given, it may be a complete
signature or a detached signature, in which case
the signed stuff is expected in a file without the
I<.sig> or I<.asc> extension (if such a file does
not exist it is expected at stdin - use B<-> as
filename to force a read from stdin). With more than
1 argument, the first should be a detached signature
and the remaining files are the signed stuff.
B<-k> [I<username>] [I<keyring>]
Kludge to be somewhat compatible with PGP.
Without arguments, all public keyrings are listed.
With one argument, only I<keyring> is listed.
Special combinations are also allowed, but they may
give strange results when combined with more options.
B<-kv> Same as B<-k>
B<-kvv> List the signatures with every key.
B<-kvvv> Additionally check all signatures.
B<-kvc> List fingerprints
B<-kvvc> List fingerprints and signatures
B<This command may be removed in the future!>
B<--list-keys> [I<names>]
B<--list-public-keys> [I<names>]
List all keys from the public keyrings, or just the
ones given on the command line.
B<--list-secret-keys> [I<names>]
List all keys from the secret keyrings, or just the
ones given on the command line.
B<--list-sigs> [I<names>]
Same as B<--list-keys>, but the signatures are listed
too.
B<--check-sigs> [I<names>]
Same as B<--list-sigs>, but the signatures are verified.
B<--fingerprint> [I<names>]
List all keys with their fingerprints. This is the
same output as B<list-keys> but with the additional output
of a line with the fingerprint. May also be combined
with B<--list-sigs> or B<--check-sigs>.
+ If this command is given twice, the fingerprints of all
+ secondary keys are listed too.
B<--list-packets>
List only the sequence of packets. This is mainly
useful for debugging.
B<--gen-key>
Generate a new key pair. This command can only be
used interactive.
B<--edit-key> I<name>
Present a menu which enables you to do all key
related tasks:
B<sign>
Make a signature on key of user I<name>.
If the key is not yet signed by the default
user (or the users given with B<-u>), the
program displays the information of the key
again, together with its fingerprint and
asks whether it should be signed. This
question is repeated for all users specified
with B<-u>.
B<lsign>
Same as B<sign> but the signature is marked as
non-exportbale and will therefore never be used
by others. This may be used to make keys valid
only in the local environment.
B<revsig>
Revoke a signature. GnuPG asks for every
every signature which has been done by one of
teh secret keys, whether a revocation
certificate should be generated.
B<trust>
Change the owner trust value. This updates the
trust-db immediately and no save is required.
B<adduid>
Create an alternate user id.
B<deluid>
Delete an user id.
B<addkey>
Add a subkey to this key.
B<delkey>
Remove a subkey.
B<revkey>
Revoke a subkey.
B<expire>
Change the key expiration time. If a key is
selected, the time of this key will be changed.
With no selection the key expiration of the
primary key is changed.
B<passwd>
Change the passphrase of the secret key.
B<uid> I<n>
Toggle selection of user id with index I<n>.
Use 0 to deselect all.
B<key> I<n>
Toggle selection of subkey with index I<n>.
Use 0 to deselect all.
B<check>
Check all selected user ids.
B<pref>
List preferences.
B<toggle>
Toggle between public and secret key listing.
B<save>
Save all changes to the key rings and quit.
B<quit>
Quit the program without updating the
key rings.
The listing shows you the key with its secondary
keys and all user ids. Selected keys or user ids
are indicated by an asterisk. The trust value is
displayed with the primary key: the first is the
assigned owner trust and the second is the calculated
trust value. Letters are used for the values:
B<-> No ownertrust assigned / not yet calculated.
B<e> Trust calculation has failed.
B<q> Not enough information for calculation.
B<n> Never trust this key.
B<m> Marginally trusted.
B<f> Fully trusted.
B<u> Ultimately trusted
B<--delete-key>
Remove key from the public keyring
B<--delete-secret-key>
Remove key from the secret and public keyring
B<--gen-revoke>
Generate a revocation certificate.
B<--export> [I<names>]
Either export all keys from all keyrings (default
keyrings and those registered via option B<--keyring>),
or if at least one name is given, those of the given
name. The new keyring is written to F<stdout> or to
the file given with option "output". Use together
with B<-a> to mail those keys.
B<--send-keys> [I<names>]
Same as B<--export> but sends the keys to a keyserver.
Option B<--keyserver> must be used to give the name
of this keyserver. Don't send your complete keyring
to a keyserver - select only those keys which are new
or changed by you.
B<--export-all> [I<names>]
Same as B<--export> but does also export keys which
are not compatible to OpenPGP.
B<--export-secret-keys> [I<names>]
Same as B<--export>, but does export the secret keys.
This is normally not very useful.
B<--import>, B<--fast-import>
Import/merge keys. The fast version does not build
the trustdb; this can be done at any time with the
command B<--update-trustdb>.
B<--recv-keys> I<key_IDs>
Import the keys with the given key IDs from a HKP
keyserver. Option B<--keyserver> must be used to
give the name of this keyserver.
B<--export-ownertrust>
List the assigned ownertrust values in ASCII format
for backup purposes
B<--import-ownertrust> [I<filename>]
Update the trustdb with the ownertrust values stored
in I<filename> (or stdin if not given); existing
values will be overwritten.
=head1 OPTIONS
Long options can be put in an options file (default F<~/.gnupg/options>).
Do not write the 2 dashes, but simply the name of the option and any
required arguments. Lines with a hash as the first non-white-space
character are ignored. Commands may be put in this file too, but that
does not make sense.
B<gpg> recognizes these options:
B<-a>, B<--armor>
Create ASCII armored output.
B<-o> I<file>, B<--output> I<file>
Write output to I<file>.
B<-u> I<name>, B<--local-user> I<name>
Use I<name> as the user-id to sign.
This option is silently ignored for the list commands,
so that it can be used in an options file.
B<--default-key> I<name>
Use I<name> as default user-id for signatures. If this
is not used the default user-id is the first user-id
from the secret keyring.
B<-r> I<name>, B<--recipient> I<name>
Encrypt for user id I<name>. If this option is not
specified, GnuPG asks for the user id.
B<--encrypt-to> I<name>
Same as B<--recipient> but this one is intended for
in the options file and may be used together with
an own user-id as an "encrypt-to-self". These keys
are only used when there are other recipients given
either by use of --recipient or by the asked user id.
No trust checking is performed for these user ids.
B<--no-encrypt-to>
Disable the use of all B<--encrypt-to> keys.
B<-v>, B<--verbose>
Give more information during processing. If used
twice, the input data is listed in detail.
B<-q>, B<--quiet>
Be somewhat more quiet in some cases.
B<-z> I<n>
Set compress level to I<n>. A value of 0 for I<n>
disables compression. Default is to use the default
compression level of zlib (normally 6).
B<-t>, B<--textmode>
Use canonical text mode. If B<-t> (but not
B<--textmode>) is used together with armoring
and signing, this enables clearsigned messages.
This kludge is needed for PGP compatibility;
normally you would use B<--sign> or B<--clearsign>
to selected the type of the signature.
B<-n>, B<--dry-run>
Don't make any changes (not yet implemented).
B<--batch>
Use batch mode. Never ask, do not allow interactive
commands.
B<--no-batch>
Disable batch mode. This may be used if B<batch>
is used in the options file.
B<--yes>
Assume "yes" on most questions.
B<--no>
Assume "no" on most questions.
B<--keyserver> I<name>
Use I<name> to lookup keys which are not yet in
your keyring. This is only done while verifying
messages with signatures. The option is also
required for the command B<--send-keys> to
specify the keyserver to where the keys should
be send. All keyservers synchronize with each
other - so there is no need to send keys to more
than one server. Using the command
"host -l pgp.net | grep wwwkeys" gives you a
list of keyservers. Because there is load
balancing using round-robin-dns you may notice
that you get different key servers.
B<--keyring> I<file>
Add I<file> to the list of keyrings.
If I<file> begins with a tilde and a slash, these
are replaced by the HOME directory. If the filename
does not contain a slash, it is assumed to be in the
home-directory (F<~/.gnupg> if B<--homedir>) is not used.
The filename may be prefixed with a scheme:
"gnupg-ring:" is the default one.
"gnupg-gdbm:" may be used for a GDBM ring.
B<--secret-keyring> I<file>
Same as B<--keyring> but for secret keyrings.
B<--homedir> I<dir>
Set the name of the home directory to I<dir>. If this
option is not used it defaults to F<~/.gnupg>. It does
not make sense to use this in a options file. This
also overrides the environment variable C<GNUPGHOME>.
B<--charset> I<name>
Set the name of the native character set. This is used
to convert some strings to proper UTF-8 encoding.
Valid values for I<name> are:
B<iso-8859-1> This is the default.
B<koi8-r> The usual Russian set (rfc1489).
B<--options> I<file>
Read options from I<file> and do not try to read
them from the default options file in the homedir
(see B<--homedir>). This option is ignored when used
in an options file.
B<--no-options>
Shortcut for B<--options> I</dev/null>. This option is
detected before an attempt to open an option file.
B<--load-extension> I<modulename>
Load an extension module. If I<modulename> does not
contain a slash it is searched in B</usr/local/lib/gnupg>
See the manual for more information about extensions.
B<--debug> I<flags>
Set debugging flags. All flags are or-ed and I<flags> may
be given in C syntax (e.g. 0x0042).
B<--debug-all>
Set all useful debugging flags.
B<--status-fd> I<n>
Write special status strings to the file descriptor I<n>.
B<--no-comment>
Do not write comment packets. This option affects only
the generation of secret keys. Output of option packets
is disabled since version 0.4.2.
B<--comment> I<string>
Use I<string> as comment string in clear text signatures.
B<--set-filename> I<string>
Use I<string> as the name of file which is stored in
messages.
B<--completes-needed> I<n>
Number of completely trusted users to introduce a new
key signer (defaults to 1).
B<--marginals-needed> I<n>
Number of marginally trusted users to introduce a new
key signer (defaults to 3)
B<--max-cert-depth> I<n>
Maximum depth of a certification chain (default is 5).
B<--cipher-algo> I<name>
Use I<name> as cipher algorithm. Running the program
with the command B<--version> yields a list of supported
algorithms. If this is not used the cipher algorithm is
selected from the preferences stored with the key.
B<--digest-algo> I<name>
Use I<name> as message digest algorithm. Running the
program with the command B<--version> yields a list of
supported algorithms. Please note that using this
option may violate the OpenPGP requirement, that a
160 bit hash is to be used for DSA.
B<--s2k-cipher-algo> I<name>
Use I<name> as the cipher algorithm used to protect secret
keys. The default cipher is BLOWFISH. This cipher is
also used for conventional encryption if B<--cipher-algo>
is not given.
B<--s2k-digest-algo> I<name>
Use I<name> as the digest algorithm used to mangle the
passphrases. The default algorithm is RIPE-MD-160.
This digest algorithm is also used for conventional
encryption if B<--digest-algo> is not given.
B<--s2k-mode> I<number>
Selects how passphrases are mangled. A number of I<0>
uses the plain passphrase (which is not recommended),
a I<1> (default) adds a salt to the passphrase and
I<3> iterates the whole process a couple of times.
Unless -B<--rfc1991> is used, this mode is also used
for conventional encryption.
B<--compress-algo> I<number>
Use compress algorithm I<number>. Default is I<2> which is
RFC1950 compression. You may use I<1> to use the old zlib
version which is used by PGP. The default algorithm may
give better results because the window size is not limited
to 8K. If this is not used the OpenPGP behavior is used,
i.e. the compression algorithm is selected from the
preferences.
B<--digest-algo> I<name>
Use I<name> as message digest algorithm. Running the
program with the command B<--version> yields a list of
supported algorithms.
B<--throw-keyid>
Do not put the keyid into encrypted packets. This option
hides the receiver of the message and is a countermeasure
against traffic analysis. It may slow down the decryption
process because all available secret keys are tried.
B<--not-dash-escaped>
This option changes the behavior of cleartext signatures
so that they can be used for patch files. You should not
send such an armored file via email because all spaces
and line endings are hashed too. You can not use this
option for data which has 5 dashes at the beginning of a
line, patch files don't have this. A special armor header
line tells GnuPG about this cleartext signature option.
B<--escape-from-lines>
Because some mailers change lines starting with "From "
to ">From " it is good to handle such lines in a special
way when creating cleartext signatures. All other PGP
versions do it this way too. This option is not enabled
by default because it would violate rfc2440.
B<--passphrase-fd> I<n>
Read the passphrase from file descriptor I<n>. If you use
0 for I<n>, the passphrase will be read from stdin. This
can only be used if only one passphrase is supplied.
B<Don't use this option if you can avoid it>
B<--rfc1991>
Try to be more RFC1991 (PGP 2.x) compliant.
B<--force-v3-sigs>
OpenPGP states that an implementation should generate
v4 signatures but PGP 5.x recognizes v4 signatures only
on key material. This options forces v3 signatures for
signatures on data.
B<--force-mdc>
Force the use of encryption with appended manipulation
code. This is always used with the newer cipher (those
with a blocksize greater than 64 bit).
B<--lock-once>
Lock the file the first time a lock is requested
and do not release the lock until the process
terminates.
B<--no-verbose>
Reset verbose level to 0.
B<--no-greeting>
Suppress the initial copyright message but do not
enter batch mode.
B<--no-armor>
Assume the input data is not in ASCII armored format.
B<--no-default-keyring>
Do not add the default keyrings to the list of
keyrings.
B<--skip-verify>
Skip the signature verification step. This may be
used to make the encryption faster if the signature
verification is not needed.
B<--version>
Print version information along with a list
of supported algorithms.
B<--with-colons>
Print key listings delimited by colons.
B<--warranty>
Print warranty information.
B<-h>, B<--help>
Print usage information.
=head1 RETURN VALUE
The Program returns 0 if everything was fine, 1 if at least
a signature was bad, and other error codes for fatal errors.
=head1 EXAMPLES
-se -r Bob [file] sign and encrypt for user Bob
-sat [file] make a clear text signature
-sb [file] make a detached signature
-k [userid] show keys
-kc [userid] show fingerprint
=head1 ENVIRONMENT
C<HOME> Used to locate the default home directory.
C<GNUPGHOME> If set directory used instead of F<~/.gnupg>.
=head1 FILES
F<~/.gnupg/secring.gpg> The secret keyring
F<~/.gnupg/secring.gpg.lock> and the lock file
F<~/.gnupg/pubring.gpg> The public keyring
F<~/.gnupg/pubring.gpg.lock> and the lock file
F<~/.gnupg/trustdb.gpg> The trust database
F<~/.gnupg/trustdb.gpg.lock> and the lock file
F<~/.gnupg/options> May contain options
F</usr[/local]/share/gnupg/options.skel> Skeleton file
F</usr[/local]/lib/gnupg/> Default location for extensions
=head1 SEE ALSO
gpg(1)
=head1 WARNINGS
Use a B<good> password for your user account and a B<good> passphrase
to protect your secret key. This passphrase is the weakest part of the
whole system. Programs to do dictionary attacks on your secret keyring
are very easy to write and so you should protect your B<~/.gnupg/>
directory very well.
Keep in mind that, if this program is used over a network (telnet), it
is B<very> easy to spy out your passphrase!
=head1 BUGS
On many systems this program should be installed as setuid(root). This
is necessary to lock memory pages. If you get no warning message about
insecure memory your OS kernel supports locking without being root.
The program drops root privileges as soon as locked memory is allocated.
diff --git a/include/mpi.h b/include/mpi.h
index ae32d1ba3..e845bec50 100644
--- a/include/mpi.h
+++ b/include/mpi.h
@@ -1,174 +1,175 @@
/* mpi.h - Multi Precision Integers
* Copyright (C) 1994, 1996, 1998 Free Software Foundation, Inc.
*
* This file is part of GNUPG.
*
* GNUPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GNUPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* Note: This code is heavily based on the GNU MP Library.
* Actually it's the same code with only minor changes in the
* way the data is stored; this is to support the abstraction
* of an optional secure memory allocation which may be used
* to avoid revealing of sensitive data due to paging etc.
* The GNU MP Library itself is published under the LGPL;
* however I decided to publish this code under the plain GPL.
*/
#ifndef G10_MPI_H
#define G10_MPI_H
#include <stdio.h>
#include "iobuf.h"
#include "types.h"
#include "memory.h"
#define DBG_MPI mpi_debug_mode
int mpi_debug_mode;
#define BITS_PER_MPI_LIMB (8*SIZEOF_UNSIGNED_LONG)
#define BYTES_PER_MPI_LIMB SIZEOF_UNSIGNED_LONG
typedef unsigned long int mpi_limb_t;
typedef signed long int mpi_limb_signed_t;
struct gcry_mpi {
int alloced; /* array size (# of allocated limbs) */
int nlimbs; /* number of valid limbs */
int nbits; /* the real number of valid bits (info only) */
int sign; /* indicates a negative number */
unsigned flags; /* bit 0: array must be allocated in secure memory space */
/* bit 1: the mpi is encrypted */
/* bit 2: the limb is a pointer to some m_alloced data */
mpi_limb_t *d; /* array with the limbs */
};
typedef struct gcry_mpi *MPI;
#define MPI_NULL NULL
#define mpi_get_nlimbs(a) ((a)->nlimbs)
#define mpi_get_nbit_info(a) ((a)->nbits)
#define mpi_set_nbit_info(a,b) ((a)->nbits = (b))
#define mpi_is_neg(a) ((a)->sign)
/*-- mpiutil.c --*/
#ifdef M_DEBUG
#define mpi_alloc(n) mpi_debug_alloc((n), M_DBGINFO( __LINE__ ) )
#define mpi_alloc_secure(n) mpi_debug_alloc_secure((n), M_DBGINFO( __LINE__ ) )
#define mpi_free(a) mpi_debug_free((a), M_DBGINFO(__LINE__) )
#define mpi_resize(a,b) mpi_debug_resize((a),(b), M_DBGINFO(__LINE__) )
#define mpi_copy(a) mpi_debug_copy((a), M_DBGINFO(__LINE__) )
MPI mpi_debug_alloc( unsigned nlimbs, const char *info );
MPI mpi_debug_alloc_secure( unsigned nlimbs, const char *info );
void mpi_debug_free( MPI a, const char *info );
void mpi_debug_resize( MPI a, unsigned nlimbs, const char *info );
MPI mpi_debug_copy( MPI a, const char *info );
#else
MPI mpi_alloc( unsigned nlimbs );
MPI mpi_alloc_secure( unsigned nlimbs );
void mpi_free( MPI a );
void mpi_resize( MPI a, unsigned nlimbs );
MPI mpi_copy( MPI a );
#endif
#define mpi_is_opaque(a) ((a) && ((a)->flags&4))
MPI mpi_set_opaque( MPI a, void *p, int len );
void *mpi_get_opaque( MPI a, int *len );
#define mpi_is_protected(a) ((a) && ((a)->flags&2))
#define mpi_set_protect_flag(a) ((a)->flags |= 2)
#define mpi_clear_protect_flag(a) ((a)->flags &= ~2)
#define mpi_is_secure(a) ((a) && ((a)->flags&1))
void mpi_set_secure( MPI a );
void mpi_clear( MPI a );
+MPI mpi_alloc_like( MPI a );
void mpi_set( MPI w, MPI u);
void mpi_set_ui( MPI w, ulong u);
MPI mpi_alloc_set_ui( unsigned long u);
void mpi_m_check( MPI a );
void mpi_swap( MPI a, MPI b);
/*-- mpicoder.c --*/
int mpi_write( IOBUF out, MPI a );
#ifdef M_DEBUG
#define mpi_read(a,b,c) mpi_debug_read((a),(b),(c), M_DBGINFO( __LINE__ ) )
MPI mpi_debug_read(IOBUF inp, unsigned *nread, int secure, const char *info);
#else
MPI mpi_read(IOBUF inp, unsigned *nread, int secure);
#endif
MPI mpi_read_from_buffer(byte *buffer, unsigned *ret_nread, int secure);
int mpi_fromstr(MPI val, const char *str);
int mpi_print( FILE *fp, MPI a, int mode );
u32 mpi_get_keyid( MPI a, u32 *keyid );
byte *mpi_get_buffer( MPI a, unsigned *nbytes, int *sign );
byte *mpi_get_secure_buffer( MPI a, unsigned *nbytes, int *sign );
void mpi_set_buffer( MPI a, const byte *buffer, unsigned nbytes, int sign );
/*-- mpi-add.c --*/
void mpi_add_ui(MPI w, MPI u, ulong v );
void mpi_add(MPI w, MPI u, MPI v);
void mpi_addm(MPI w, MPI u, MPI v, MPI m);
void mpi_sub_ui(MPI w, MPI u, ulong v );
void mpi_sub( MPI w, MPI u, MPI v);
void mpi_subm( MPI w, MPI u, MPI v, MPI m);
/*-- mpi-mul.c --*/
void mpi_mul_ui(MPI w, MPI u, ulong v );
void mpi_mul_2exp( MPI w, MPI u, ulong cnt);
void mpi_mul( MPI w, MPI u, MPI v);
void mpi_mulm( MPI w, MPI u, MPI v, MPI m);
/*-- mpi-div.c --*/
ulong mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor );
void mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor );
void mpi_fdiv_q( MPI quot, MPI dividend, MPI divisor );
void mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor );
void mpi_tdiv_r( MPI rem, MPI num, MPI den);
void mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den);
void mpi_tdiv_q_2exp( MPI w, MPI u, unsigned count );
int mpi_divisible_ui(MPI dividend, ulong divisor );
/*-- mpi-gcd.c --*/
int mpi_gcd( MPI g, MPI a, MPI b );
/*-- mpi-pow.c --*/
void mpi_pow( MPI w, MPI u, MPI v);
void mpi_powm( MPI res, MPI base, MPI exp, MPI mod);
/*-- mpi-mpow.c --*/
void mpi_mulpowm( MPI res, MPI *basearray, MPI *exparray, MPI mod);
/*-- mpi-cmp.c --*/
int mpi_cmp_ui( MPI u, ulong v );
int mpi_cmp( MPI u, MPI v );
/*-- mpi-scan.c --*/
int mpi_getbyte( MPI a, unsigned idx );
void mpi_putbyte( MPI a, unsigned idx, int value );
unsigned mpi_trailing_zeros( MPI a );
/*-- mpi-bit.c --*/
void mpi_normalize( MPI a );
unsigned mpi_get_nbits( MPI a );
int mpi_test_bit( MPI a, unsigned n );
void mpi_set_bit( MPI a, unsigned n );
void mpi_set_highbit( MPI a, unsigned n );
void mpi_clear_highbit( MPI a, unsigned n );
void mpi_clear_bit( MPI a, unsigned n );
void mpi_rshift( MPI x, MPI a, unsigned n );
/*-- mpi-inv.c --*/
void mpi_invm( MPI x, MPI u, MPI v );
#endif /*G10_MPI_H*/
diff --git a/mpi/ChangeLog b/mpi/ChangeLog
index 7d66b809b..10e3bddd6 100644
--- a/mpi/ChangeLog
+++ b/mpi/ChangeLog
@@ -1,146 +1,150 @@
+Tue May 4 15:47:53 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
+
+ * mpiutil.c (mpi_alloc_like): New.
+
Mon Apr 26 17:48:15 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* mpih-add.c, mpih-sub.c: Removed
* mpi-inline.c: New.
* mpi-inline.h: Make it usable by mpi-inline.c.
Sun Apr 18 10:11:28 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* mpih-mul.c (mpihelp_mul_n): Fixed use of memory region.
(mpihelp_mul): Ditto.
Wed Apr 7 20:51:39 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* Makefile.am: Explicit rules to invoke cpp on *.S
Mon Mar 8 20:47:17 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* config.links: Take advantage of the with_symbol_underscore macro.
Add support for freebsd 4.
Wed Feb 24 11:07:27 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* mips3/mpih-sub1.S: Removed left over junk in last line. (Should I
blame me or my editor?).
Sat Feb 13 12:04:43 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* Makefile.am: Removed the +=. Add MPI_OPT_FLAGS.
Sat Jan 9 16:02:23 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* mpi-cmp.c (mpi_cmp_ui): Normalized the arg.
Thu Jan 7 18:00:58 CET 1999 Werner Koch <wk@isil.d.shuttle.de>
* mpi-bit.c (mpi_normalize): New.
(mpi_get_nbits): Normalize the MPI.
* mpi-bit.c (mpi_cmp): Normalize the MPI before the compare.
Tue Dec 8 13:15:16 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* config.links: Moved the case for powerpc*linux
* powerpcp32/*.S: Removed some underscores.
Thu Nov 26 07:27:52 1998 Werner Koch <werner.koch@guug.de>
* config.links: Support for ppc with ELF
* powerpc32/syntax.h: New.
* powerpc32/*.S: Applied ELF patches (glibc patches)
Tue Nov 10 19:31:37 1998 Werner Koch (wk@isil.d.shuttle.de)
* power*/ : Started with stuff for PPC
* config.links: Some stuff for PPC.
* generic/udiv-w-sdiv.c: New but disabled.
Tue Oct 27 12:37:46 1998 Werner Koch (wk@isil.d.shuttle.de)
* config.links (freebsd): Fixes for FreeBSD 3.0
Wed Oct 14 09:59:30 1998 Werner Koch (wk@isil.d.shuttle.de)
* config.links (freebsd): ELF patches from Jun Kuriyama.
Thu Oct 8 13:28:17 1998 Werner Koch (wk@isil.d.shuttle.de)
* mpi-mpow.c (mpi_mulpowm): Fixed mem leak (m_free/mpi_free).
Thu Sep 17 18:08:50 1998 Werner Koch (wk@(none))
* hppa1.1/udiv-qrnnd.S: Fix from Steffen Zahn for HPUX 10.20
Thu Aug 6 16:39:28 1998 Werner Koch,mobil,,, (wk@tobold)
* mpi-bit.c (mpi_set_bytes): Removed.
Wed Aug 5 15:11:12 1998 Werner Koch (wk@(none))
* mpicoder.c (mpi_read_from_buffer): New.
* mpiutil.c (mpi_set_opaque): New.
(mpi_get_opaque): New.
(mpi_copy): Changed to support opauqe flag
(mpi_free): Ditto.
Sat Jul 4 10:11:11 1998 Werner Koch (wk@isil.d.shuttle.de)
* mpiutil.c (mpi_clear): Reset flags.
(mpi_set): Ditto.
(mpi_alloc_secure): Set flag to 1 and not ored the 1 in, tsss..
Fri Jun 26 11:19:06 1998 Werner Koch (wk@isil.d.shuttle.de)
* mpiutil.c (mpi_alloc): set nbits to 0.
(mpi_alloc_secure): Ditto.
(mpi_clear): Ditto.
Thu Jun 25 11:50:01 1998 Werner Koch (wk@isil.d.shuttle.de)
* mips3/*.S: New
Mon May 18 13:47:06 1998 Werner Koch (wk@isil.d.shuttle.de)
* config.links: split mpih-shift into mpih-[lr]shift and
changed all implementations.
* mpi/alpha: add some new assembler stuff.
Wed May 13 11:04:29 1998 Werner Koch (wk@isil.d.shuttle.de)
* config.links: Add support for MIPS
Thu Apr 9 11:31:36 1998 Werner Koch (wk@isil.d.shuttle.de)
* mpicoder.c (mpi_get_secure_buffer): New.
Wed Apr 8 09:44:33 1998 Werner Koch (wk@isil.d.shuttle.de)
* config.links: Applied small fix from Ulf Möller.
Mon Apr 6 12:38:52 1998 Werner Koch (wk@isil.d.shuttle.de)
* mpicoder.c (mpi_get_buffer): Removed returned leading zeroes
and changed all callers.
Tue Mar 10 13:40:34 1998 Werner Koch (wk@isil.d.shuttle.de)
* mpi-bit.c (mpi_clear_highbit): New.
Mon Mar 2 19:29:00 1998 Werner Koch (wk@isil.d.shuttle.de)
* Makefile.am (DISTCLEANFILES): New
Thu Feb 26 06:48:54 1998 Werner Koch (wk@isil.d.shuttle.de)
* config.links (X86_BROKEN_ALIGN): Added for some systems.
Mon Feb 23 12:21:40 1998 Werner Koch (wk@isil.d.shuttle.de)
* mpi/m68k/mpih-shift.S (Lspecial): Changed duplicate symbol.
Mon Feb 16 13:00:27 1998 Werner Koch (wk@isil.d.shuttle.de)
* config.links : Add detection of m68k cpus
diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c
index 82ba87112..cbbe10d25 100644
--- a/mpi/mpiutil.c
+++ b/mpi/mpiutil.c
@@ -1,378 +1,408 @@
/* mpiutil.ac - Utility functions for MPI
* Copyright (C) 1998 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* GnuPG is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GnuPG is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "mpi.h"
#include "mpi-internal.h"
#include "memory.h"
#include "util.h"
#ifdef M_DEBUG
#undef mpi_alloc
#undef mpi_alloc_secure
#undef mpi_free
#endif
/****************
* Note: It was a bad idea to use the number of limbs to allocate
* because on a alpha the limbs are large but we normally need
* integers of n bits - So we should chnage this to bits (or bytes).
*
* But mpi_alloc is used in a lot of places :-)
*/
MPI
#ifdef M_DEBUG
mpi_debug_alloc( unsigned nlimbs, const char *info )
#else
mpi_alloc( unsigned nlimbs )
#endif
{
MPI a;
if( DBG_MEMORY )
log_debug("mpi_alloc(%u)\n", nlimbs*BITS_PER_MPI_LIMB );
#ifdef M_DEBUG
a = m_debug_alloc( sizeof *a, info );
a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 0, info ) : NULL;
#else
a = m_alloc( sizeof *a );
a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 0 ) : NULL;
#endif
a->alloced = nlimbs;
a->nlimbs = 0;
a->sign = 0;
a->flags = 0;
a->nbits = 0;
return a;
}
void
mpi_m_check( MPI a )
{
m_check(a);
m_check(a->d);
}
MPI
#ifdef M_DEBUG
mpi_debug_alloc_secure( unsigned nlimbs, const char *info )
#else
mpi_alloc_secure( unsigned nlimbs )
#endif
{
MPI a;
if( DBG_MEMORY )
log_debug("mpi_alloc_secure(%u)\n", nlimbs*BITS_PER_MPI_LIMB );
#ifdef M_DEBUG
a = m_debug_alloc( sizeof *a, info );
a->d = nlimbs? mpi_debug_alloc_limb_space( nlimbs, 1, info ) : NULL;
#else
a = m_alloc( sizeof *a );
a->d = nlimbs? mpi_alloc_limb_space( nlimbs, 1 ) : NULL;
#endif
a->alloced = nlimbs;
a->flags = 1;
a->nlimbs = 0;
a->sign = 0;
a->nbits = 0;
return a;
}
mpi_ptr_t
#ifdef M_DEBUG
mpi_debug_alloc_limb_space( unsigned nlimbs, int secure, const char *info )
#else
mpi_alloc_limb_space( unsigned nlimbs, int secure )
#endif
{
size_t len = nlimbs * sizeof(mpi_limb_t);
if( DBG_MEMORY )
log_debug("mpi_alloc_limb_space(%u)\n", (unsigned)len*8 );
#ifdef M_DEBUG
return secure? m_debug_alloc_secure(len, info):m_debug_alloc( len, info );
#else
return secure? m_alloc_secure( len ):m_alloc( len );
#endif
}
void
#ifdef M_DEBUG
mpi_debug_free_limb_space( mpi_ptr_t a, const char *info )
#else
mpi_free_limb_space( mpi_ptr_t a )
#endif
{
if( !a )
return;
if( DBG_MEMORY )
log_debug("mpi_free_limb_space of size %lu\n", (ulong)m_size(a)*8 );
m_free(a);
}
void
mpi_assign_limb_space( MPI a, mpi_ptr_t ap, unsigned nlimbs )
{
mpi_free_limb_space(a->d);
a->d = ap;
a->alloced = nlimbs;
}
/****************
* Resize the array of A to NLIMBS. the additional space is cleared
* (set to 0) [done by m_realloc()]
*/
void
#ifdef M_DEBUG
mpi_debug_resize( MPI a, unsigned nlimbs, const char *info )
#else
mpi_resize( MPI a, unsigned nlimbs )
#endif
{
if( nlimbs <= a->alloced )
return; /* no need to do it */
/* Note: a->secure is not used - instead the realloc functions
* take care of it. Maybe we should drop a->secure completely
* and rely on a mpi_is_secure function, which would be
* a wrapper around m_is_secure
*/
#ifdef M_DEBUG
if( a->d )
a->d = m_debug_realloc(a->d, nlimbs * sizeof(mpi_limb_t), info );
else
a->d = m_debug_alloc_clear( nlimbs * sizeof(mpi_limb_t), info );
#else
if( a->d )
a->d = m_realloc(a->d, nlimbs * sizeof(mpi_limb_t) );
else
a->d = m_alloc_clear( nlimbs * sizeof(mpi_limb_t) );
#endif
a->alloced = nlimbs;
}
void
mpi_clear( MPI a )
{
a->nlimbs = 0;
a->nbits = 0;
a->flags = 0;
}
void
#ifdef M_DEBUG
mpi_debug_free( MPI a, const char *info )
#else
mpi_free( MPI a )
#endif
{
if( !a )
return;
if( DBG_MEMORY )
log_debug("mpi_free\n" );
if( a->flags & 4 )
m_free( a->d );
else {
#ifdef M_DEBUG
mpi_debug_free_limb_space(a->d, info);
#else
mpi_free_limb_space(a->d);
#endif
}
if( a->flags & ~7 )
log_bug("invalid flag value in mpi\n");
m_free(a);
}
void
mpi_set_secure( MPI a )
{
mpi_ptr_t ap, bp;
if( (a->flags & 1) )
return;
a->flags |= 1;
ap = a->d;
if( !a->nlimbs ) {
assert(!ap);
return;
}
#ifdef M_DEBUG
bp = mpi_debug_alloc_limb_space( a->nlimbs, 1, "set_secure" );
#else
bp = mpi_alloc_limb_space( a->nlimbs, 1 );
#endif
MPN_COPY( bp, ap, a->nlimbs );
a->d = bp;
#ifdef M_DEBUG
mpi_debug_free_limb_space(ap, "set_secure");
#else
mpi_free_limb_space(ap);
#endif
}
MPI
mpi_set_opaque( MPI a, void *p, int len )
{
if( !a ) {
#ifdef M_DEBUG
a = mpi_debug_alloc(0,"alloc_opaque");
#else
a = mpi_alloc(0);
#endif
}
if( a->flags & 4 )
m_free( a->d );
else {
#ifdef M_DEBUG
mpi_debug_free_limb_space(a->d, "alloc_opaque");
#else
mpi_free_limb_space(a->d);
#endif
}
a->d = p;
a->alloced = 0;
a->nlimbs = 0;
a->nbits = len;
a->flags = 4;
return a;
}
void *
mpi_get_opaque( MPI a, int *len )
{
if( !(a->flags & 4) )
log_bug("mpi_get_opaque on normal mpi\n");
if( len )
*len = a->nbits;
return a->d;
}
/****************
* Note: This copy function should not interpret the MPI
* but copy it transparently.
*/
MPI
#ifdef M_DEBUG
mpi_debug_copy( MPI a, const char *info )
#else
mpi_copy( MPI a )
#endif
{
int i;
MPI b;
if( a && (a->flags & 4) ) {
void *p = m_is_secure(a->d)? m_alloc_secure( a->nbits )
: m_alloc( a->nbits );
memcpy( p, a->d, a->nbits );
b = mpi_set_opaque( NULL, p, a->nbits );
}
else if( a ) {
#ifdef M_DEBUG
b = mpi_is_secure(a)? mpi_debug_alloc_secure( a->nlimbs, info )
: mpi_debug_alloc( a->nlimbs, info );
#else
b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
: mpi_alloc( a->nlimbs );
#endif
b->nlimbs = a->nlimbs;
b->sign = a->sign;
b->flags = a->flags;
b->nbits = a->nbits;
for(i=0; i < b->nlimbs; i++ )
b->d[i] = a->d[i];
}
else
b = NULL;
return b;
}
+/****************
+ * This function allocates an MPI which is optimized to hold
+ * a value as large as the one given in the arhgument and allocates it
+ * with the same flags as A.
+ */
+MPI
+mpi_alloc_like( MPI a )
+{
+ MPI b;
+
+ if( a && (a->flags & 4) ) {
+ void *p = m_is_secure(a->d)? m_alloc_secure( a->nbits )
+ : m_alloc( a->nbits );
+ memcpy( p, a->d, a->nbits );
+ b = mpi_set_opaque( NULL, p, a->nbits );
+ }
+ else if( a ) {
+ b = mpi_is_secure(a)? mpi_alloc_secure( a->nlimbs )
+ : mpi_alloc( a->nlimbs );
+ b->nlimbs = 0;
+ b->sign = 0;
+ b->flags = a->flags;
+ b->nbits = 0;
+ }
+ else
+ b = NULL;
+ return b;
+}
+
+
void
mpi_set( MPI w, MPI u)
{
mpi_ptr_t wp, up;
mpi_size_t usize = u->nlimbs;
int usign = u->sign;
RESIZE_IF_NEEDED(w, usize);
wp = w->d;
up = u->d;
MPN_COPY( wp, up, usize );
w->nlimbs = usize;
w->nbits = u->nbits;
w->flags = u->flags;
w->sign = usign;
}
void
mpi_set_ui( MPI w, unsigned long u)
{
RESIZE_IF_NEEDED(w, 1);
w->d[0] = u;
w->nlimbs = u? 1:0;
w->sign = 0;
w->nbits = 0;
w->flags = 0;
}
MPI
mpi_alloc_set_ui( unsigned long u)
{
#ifdef M_DEBUG
MPI w = mpi_debug_alloc(1,"alloc_set_ui");
#else
MPI w = mpi_alloc(1);
#endif
w->d[0] = u;
w->nlimbs = u? 1:0;
w->sign = 0;
return w;
}
void
mpi_swap( MPI a, MPI b)
{
struct gcry_mpi tmp;
tmp = *a; *a = *b; *b = tmp;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Feb 26, 6:43 PM (14 h, 57 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
3b/e4/ac0b5094a4479378951c3f3c2b16

Event Timeline