mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
edit-key is now complete
This commit is contained in:
parent
1a80de41a5
commit
5ae562b41d
4
AUTHORS
4
AUTHORS
@ -6,3 +6,7 @@ Werner Koch. Designed and implemented gnupg.
|
||||
TRANSLATIONS Marco d'Itri 1997-02-22
|
||||
Disclaim
|
||||
|
||||
Twofish Matthew Skala ????????????
|
||||
|
||||
|
||||
|
||||
|
25
NEWS
25
NEWS
@ -1,12 +1,37 @@
|
||||
Noteworthy changes in version 0.3.3
|
||||
-----------------------------------
|
||||
* The format of the trust database has changed; you must delete
|
||||
the old one, so gnupg can create a new one.
|
||||
IMPORTANT: Use version 0.3.[12] to save your assigned ownertrusts
|
||||
("gpgm --list-ownertrust >saved-trust"); then build this new version
|
||||
and restore the ownertrust with this new version
|
||||
("gpgm --import-ownertrust saved-trust").
|
||||
|
||||
* The command --edit-key now provides a commandline driven menu
|
||||
which can be used vor vaious tasks. --sign-key is only an
|
||||
an alias to --edit-key and maybe removed in future: use the
|
||||
command "sign" of this new menu - you can select which user ids
|
||||
you want to sign.
|
||||
|
||||
* Alternate user ids can now be created an signed.
|
||||
|
||||
* Removed options --gen-prime and --gen-random.
|
||||
|
||||
* Removed option --add-key; use --edit-key instead.
|
||||
|
||||
* Removed option --change-passphrase; use --edit-key instead.
|
||||
|
||||
* Signatures are now checked even if the output file could not
|
||||
be created. Command "--verify" tries to find the detached data.
|
||||
|
||||
* gpg now disables core dumps.
|
||||
|
||||
* We have added the Twofish as an experimental cipher algorithm.
|
||||
Many thanks to Matthew Skala for doing this work.
|
||||
Twofish is the AES submission from Schneier et al.; see
|
||||
"www.counterpane.com/twofish.html" for more information.
|
||||
|
||||
|
||||
|
||||
Noteworthy changes in version 0.3.2
|
||||
-----------------------------------
|
||||
|
3
README
3
README
@ -135,6 +135,9 @@
|
||||
|
||||
Creates a signature of file, but writes the output to the file "out".
|
||||
|
||||
If you use the option "--rfc1991", gnupg tries to me more compatible
|
||||
to RFC1991 (pgp 2.x).
|
||||
|
||||
|
||||
Encrypt
|
||||
-------
|
||||
|
3
THANKS
3
THANKS
@ -5,6 +5,7 @@ errors.
|
||||
|
||||
Anand Kumria wildfire@progsoc.uts.edu.au
|
||||
Brian Warner warner@lothar.com
|
||||
Caskey L. Dickson caskey@technocage.com
|
||||
Charles Levert charles@comm.polymtl.ca
|
||||
Christian von Roques roques@pond.sub.org
|
||||
Daniel Eisenbud eisenbud@cs.swarthmore.edu
|
||||
@ -25,8 +26,10 @@ Martin Schulte schulte@thp.uni-koeln.de
|
||||
Matthew Skala mskala@ansuz.sooke.bc.ca
|
||||
Max Valianskiy maxcom@maxcom.ml.org
|
||||
Nicolas Graner Nicolas.Graner@cri.u-psud.fr
|
||||
Oskari Jääskeläinen f33003a@cc.hut.fi
|
||||
Peter Gutmann pgut001@cs.auckland.ac.nz
|
||||
Ralph Gillen gillen@theochem.uni-duesseldorf.de
|
||||
Steffen Ullrich ccrlphr@xensei.com
|
||||
Thomas Roessler roessler@guug.de
|
||||
Tom Spindler dogcow@home.merit.edu
|
||||
Tom Zerucha tzeruch@ceddec.com
|
||||
|
16
TODO
16
TODO
@ -2,6 +2,16 @@
|
||||
can also hold the localid and extend the localid to hold information
|
||||
of the subkey number because two subkeys may have the same keyid.
|
||||
|
||||
* Fix Oscaris problems with the trustdb.
|
||||
|
||||
* add test cases for invalid data (scrambled armor or other random data)
|
||||
|
||||
* fix the expire stuff for v4 packets.
|
||||
|
||||
* check whether it is valid to pack the signature stuff (onepass, data,
|
||||
sig) into a compressed packet - or should we only compress the data?
|
||||
what does pgp 5 do, what does OpenPGP say=
|
||||
|
||||
* invalid packets (Marco)
|
||||
|
||||
* add some sanity checks to read_keyblock, so that we are sure that
|
||||
@ -9,9 +19,7 @@
|
||||
|
||||
* what about the CR,LF in cleartext singatures?
|
||||
|
||||
* add option --restore-ownertrust
|
||||
|
||||
* always put key signatures before the first subkey.
|
||||
* add option --import-ownertrust
|
||||
|
||||
* add a way to delete subkeys (in edit-keys?)
|
||||
|
||||
@ -33,8 +41,6 @@
|
||||
* add checking of armor trailers
|
||||
* remove all "Fixmes"
|
||||
|
||||
* add an option to create a new user id.
|
||||
|
||||
* add an option to re-create a public key from a secret key. Think about
|
||||
a backup system of only the secret part of the secret key.
|
||||
|
||||
|
@ -61,10 +61,10 @@ chdir () {
|
||||
|
||||
|
||||
set -e
|
||||
pgmname=$(basename $0)
|
||||
pgmname=`basename $0`
|
||||
#trap cleanup SIGHUP SIGINT SIGQUIT
|
||||
|
||||
[ -z $srcdir ] && fatal "not called from make"
|
||||
[ -z "$srcdir" ] && fatal "not called from make"
|
||||
|
||||
cat <<EOF >./options
|
||||
no-greeting
|
||||
|
@ -1,3 +1,10 @@
|
||||
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.
|
||||
|
@ -1,6 +1,6 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
gnupg_extensions = tiger
|
||||
gnupg_extensions = tiger twofish
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl -I../intl
|
||||
|
||||
@ -42,9 +42,13 @@ libcipher_a_SOURCES = cipher.c \
|
||||
smallprime.c
|
||||
|
||||
EXTRA_tiger_SOURCES = tiger.c
|
||||
EXTRA_twofish_SOURCES = twofish.c
|
||||
|
||||
tiger: tiger.c
|
||||
$(COMPILE) -shared -fPIC -o tiger tiger.c
|
||||
$(COMPILE) -shared -fPIC -o tiger tiger.c
|
||||
|
||||
twofish: twofish.c
|
||||
$(COMPILE) -shared -fPIC -o twofish twofish.c
|
||||
|
||||
install-exec-hook:
|
||||
@list='$(pkglib_PROGRAMS)'; for p in $$list; do \
|
||||
|
158
cipher/cipher.c
158
cipher/cipher.c
@ -34,12 +34,13 @@
|
||||
#include "dynload.h"
|
||||
|
||||
|
||||
#define STD_BLOCKSIZE 8
|
||||
#define MAX_BLOCKSIZE 16
|
||||
#define TABLE_SIZE 10
|
||||
|
||||
struct cipher_table_s {
|
||||
const char *name;
|
||||
int algo;
|
||||
size_t blocksize;
|
||||
size_t keylen;
|
||||
size_t contextsize; /* allocate this amount of context */
|
||||
void (*setkey)( void *c, byte *key, unsigned keylen );
|
||||
@ -53,8 +54,9 @@ static struct cipher_table_s cipher_table[TABLE_SIZE];
|
||||
struct cipher_handle_s {
|
||||
int algo;
|
||||
int mode;
|
||||
byte iv[STD_BLOCKSIZE]; /* (this should be ulong aligned) */
|
||||
byte lastiv[STD_BLOCKSIZE];
|
||||
size_t blocksize;
|
||||
byte iv[MAX_BLOCKSIZE]; /* (this should be ulong aligned) */
|
||||
byte lastiv[MAX_BLOCKSIZE];
|
||||
int unused; /* in IV */
|
||||
void (*setkey)( void *c, byte *key, unsigned keylen );
|
||||
void (*encrypt)( void *c, byte *outbuf, byte *inbuf );
|
||||
@ -80,44 +82,44 @@ setup_cipher_table()
|
||||
{
|
||||
|
||||
int i;
|
||||
size_t blocksize;
|
||||
|
||||
i = 0;
|
||||
cipher_table[i].algo = CIPHER_ALGO_BLOWFISH;
|
||||
cipher_table[i].name = blowfish_get_info( cipher_table[i].algo,
|
||||
&cipher_table[i].keylen,
|
||||
&blocksize,
|
||||
&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 || blocksize != STD_BLOCKSIZE )
|
||||
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,
|
||||
&blocksize,
|
||||
&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 || blocksize != STD_BLOCKSIZE )
|
||||
if( !cipher_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
cipher_table[i].algo = CIPHER_ALGO_BLOWFISH160;
|
||||
cipher_table[i].name = blowfish_get_info( cipher_table[i].algo,
|
||||
&cipher_table[i].keylen,
|
||||
&blocksize,
|
||||
&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 || blocksize != STD_BLOCKSIZE )
|
||||
if( !cipher_table[i].name )
|
||||
BUG();
|
||||
i++;
|
||||
cipher_table[i].algo = CIPHER_ALGO_DUMMY;
|
||||
cipher_table[i].name = "DUMMY";
|
||||
cipher_table[i].blocksize = 8;
|
||||
cipher_table[i].keylen = 128;
|
||||
cipher_table[i].contextsize = 0;
|
||||
cipher_table[i].setkey = dummy_setkey;
|
||||
@ -141,7 +143,6 @@ load_cipher_modules()
|
||||
void *context = NULL;
|
||||
struct cipher_table_s *ct;
|
||||
int ct_idx;
|
||||
size_t blocksize;
|
||||
int i;
|
||||
const char *name;
|
||||
int any = 0;
|
||||
@ -164,9 +165,9 @@ load_cipher_modules()
|
||||
BUG(); /* table already full */
|
||||
/* now load all extensions */
|
||||
while( (name = enum_gnupgext_ciphers( &context, &ct->algo,
|
||||
&ct->keylen, &blocksize, &ct->contextsize,
|
||||
&ct->keylen, &ct->blocksize, &ct->contextsize,
|
||||
&ct->setkey, &ct->encrypt, &ct->decrypt)) ) {
|
||||
if( blocksize != STD_BLOCKSIZE ) {
|
||||
if( ct->blocksize != 8 && ct->blocksize != 16 ) {
|
||||
log_info("skipping cipher %d: unsupported blocksize\n", ct->algo);
|
||||
continue;
|
||||
}
|
||||
@ -271,6 +272,26 @@ cipher_get_keylen( int 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
|
||||
@ -299,6 +320,7 @@ cipher_open( int algo, int mode, int secure )
|
||||
+ cipher_table[i].contextsize )
|
||||
: m_alloc_clear( sizeof *hd + cipher_table[i].contextsize );
|
||||
hd->algo = algo;
|
||||
hd->blocksize = cipher_table[i].blocksize;
|
||||
hd->setkey = cipher_table[i].setkey;
|
||||
hd->encrypt = cipher_table[i].encrypt;
|
||||
hd->decrypt = cipher_table[i].decrypt;
|
||||
@ -336,9 +358,9 @@ void
|
||||
cipher_setiv( CIPHER_HANDLE c, const byte *iv )
|
||||
{
|
||||
if( iv )
|
||||
memcpy( c->iv, iv, STD_BLOCKSIZE );
|
||||
memcpy( c->iv, iv, c->blocksize );
|
||||
else
|
||||
memset( c->iv, 0, STD_BLOCKSIZE );
|
||||
memset( c->iv, 0, c->blocksize );
|
||||
c->unused = 0;
|
||||
}
|
||||
|
||||
@ -351,8 +373,8 @@ do_ecb_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks )
|
||||
|
||||
for(n=0; n < nblocks; n++ ) {
|
||||
(*c->encrypt)( &c->context, outbuf, inbuf );
|
||||
inbuf += STD_BLOCKSIZE;;
|
||||
outbuf += STD_BLOCKSIZE;
|
||||
inbuf += c->blocksize;
|
||||
outbuf += c->blocksize;
|
||||
}
|
||||
}
|
||||
|
||||
@ -363,8 +385,8 @@ do_ecb_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nblocks )
|
||||
|
||||
for(n=0; n < nblocks; n++ ) {
|
||||
(*c->decrypt)( &c->context, outbuf, inbuf );
|
||||
inbuf += STD_BLOCKSIZE;;
|
||||
outbuf += STD_BLOCKSIZE;
|
||||
inbuf += c->blocksize;
|
||||
outbuf += c->blocksize;
|
||||
}
|
||||
}
|
||||
|
||||
@ -373,11 +395,12 @@ 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+STD_BLOCKSIZE - c->unused; nbytes; nbytes--, c->unused-- )
|
||||
for(ivp=c->iv+c->blocksize - c->unused; nbytes; nbytes--, c->unused-- )
|
||||
*outbuf++ = (*ivp++ ^= *inbuf++);
|
||||
return;
|
||||
}
|
||||
@ -385,26 +408,26 @@ do_cfb_encrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
|
||||
if( c->unused ) {
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
nbytes -= c->unused;
|
||||
for(ivp=c->iv+STD_BLOCKSIZE - c->unused; c->unused; c->unused-- )
|
||||
for(ivp=c->iv+blocksize - c->unused; c->unused; c->unused-- )
|
||||
*outbuf++ = (*ivp++ ^= *inbuf++);
|
||||
}
|
||||
|
||||
/* now we can process complete blocks */
|
||||
while( nbytes >= STD_BLOCKSIZE ) {
|
||||
while( nbytes >= blocksize ) {
|
||||
int i;
|
||||
/* encrypt the IV (and save the current one) */
|
||||
memcpy( c->lastiv, c->iv, STD_BLOCKSIZE );
|
||||
memcpy( c->lastiv, c->iv, blocksize );
|
||||
(*c->encrypt)( &c->context, c->iv, c->iv );
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
for(ivp=c->iv,i=0; i < STD_BLOCKSIZE; i++ )
|
||||
for(ivp=c->iv,i=0; i < blocksize; i++ )
|
||||
*outbuf++ = (*ivp++ ^= *inbuf++);
|
||||
nbytes -= STD_BLOCKSIZE;
|
||||
nbytes -= blocksize;
|
||||
}
|
||||
if( nbytes ) { /* process the remaining bytes */
|
||||
/* encrypt the IV (and save the current one) */
|
||||
memcpy( c->lastiv, c->iv, STD_BLOCKSIZE );
|
||||
memcpy( c->lastiv, c->iv, blocksize );
|
||||
(*c->encrypt)( &c->context, c->iv, c->iv );
|
||||
c->unused = STD_BLOCKSIZE;
|
||||
c->unused = blocksize;
|
||||
/* and apply the xor */
|
||||
c->unused -= nbytes;
|
||||
for(ivp=c->iv; nbytes; nbytes-- )
|
||||
@ -417,11 +440,12 @@ 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+STD_BLOCKSIZE - c->unused; nbytes; nbytes--,c->unused--){
|
||||
for(ivp=c->iv+blocksize - c->unused; nbytes; nbytes--,c->unused--){
|
||||
temp = *inbuf++;
|
||||
*outbuf++ = *ivp ^ temp;
|
||||
*ivp++ = temp;
|
||||
@ -432,7 +456,7 @@ do_cfb_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
|
||||
if( c->unused ) {
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
nbytes -= c->unused;
|
||||
for(ivp=c->iv+STD_BLOCKSIZE - c->unused; c->unused; c->unused-- ) {
|
||||
for(ivp=c->iv+blocksize - c->unused; c->unused; c->unused-- ) {
|
||||
temp = *inbuf++;
|
||||
*outbuf++ = *ivp ^ temp;
|
||||
*ivp++ = temp;
|
||||
@ -440,70 +464,24 @@ do_cfb_decrypt( CIPHER_HANDLE c, byte *outbuf, byte *inbuf, unsigned nbytes )
|
||||
}
|
||||
|
||||
/* now we can process complete blocks */
|
||||
#ifdef BIG_ENDIAN_HOST
|
||||
/* This does only make sense for big endian hosts, due to ... ivp = temp*/
|
||||
if( !((ulong)inbuf % SIZEOF_UNSIGNED_LONG) ) {
|
||||
while( nbytes >= STD_BLOCKSIZE ) {
|
||||
/* encrypt the IV (and save the current one) */
|
||||
memcpy( c->lastiv, c->iv, STD_BLOCKSIZE );
|
||||
(*c->encrypt)( &c->context, c->iv, c->iv );
|
||||
ivp = c->iv;
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
#if SIZEOF_UNSIGNED_LONG == STD_BLOCKSIZE
|
||||
temp = *(ulong*)inbuf;
|
||||
*(ulong*)outbuf = *(ulong*)c->iv ^ temp;
|
||||
*(ulong*)ivp = temp;
|
||||
#elif (2*SIZEOF_UNSIGNED_LONG) == STD_BLOCKSIZE
|
||||
temp = ((ulong*)inbuf)[0];
|
||||
((ulong*)outbuf)[0] = ((ulong*)c->iv)[0] ^ temp;
|
||||
((ulong*)ivp)[0] = temp;
|
||||
temp = ((ulong*)inbuf)[1];
|
||||
((ulong*)outbuf)[1] = ((ulong*)c->iv)[1] ^ temp;
|
||||
((ulong*)ivp)[1] = temp;
|
||||
#elif (4*SIZEOF_UNSIGNED_LONG) == STD_BLOCKSIZE
|
||||
temp = ((ulong*)inbuf)[0];
|
||||
((ulong*)outbuf)[0] = ((ulong*)c->iv)[0] ^ temp;
|
||||
((ulong*)ivp)[0] = temp;
|
||||
temp = ((ulong*)inbuf)[1];
|
||||
((ulong*)outbuf)[1] = ((ulong*)c->iv)[1] ^ temp;
|
||||
((ulong*)ivp)[1] = temp;
|
||||
temp = ((ulong*)inbuf)[2];
|
||||
((ulong*)outbuf)[2] = ((ulong*)c->iv)[2] ^ temp;
|
||||
((ulong*)ivp)[2] = temp;
|
||||
temp = ((ulong*)inbuf)[3];
|
||||
((ulong*)outbuf)[3] = ((ulong*)c->iv)[3] ^ temp;
|
||||
((ulong*)ivp)[3] = temp;
|
||||
#else
|
||||
#error Please disable the align test.
|
||||
#endif
|
||||
nbytes -= STD_BLOCKSIZE;
|
||||
inbuf += STD_BLOCKSIZE;
|
||||
outbuf += STD_BLOCKSIZE;
|
||||
while( nbytes >= blocksize ) {
|
||||
int i;
|
||||
/* encrypt the IV (and save the current one) */
|
||||
memcpy( c->lastiv, c->iv, blocksize );
|
||||
(*c->encrypt)( &c->context, c->iv, c->iv );
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
for(ivp=c->iv,i=0; i < blocksize; i++ ) {
|
||||
temp = *inbuf++;
|
||||
*outbuf++ = *ivp ^ temp;
|
||||
*ivp++ = temp;
|
||||
}
|
||||
nbytes -= blocksize;
|
||||
}
|
||||
else { /* non aligned version */
|
||||
#endif /* BIG_ENDIAN_HOST */
|
||||
while( nbytes >= STD_BLOCKSIZE ) {
|
||||
int i;
|
||||
/* encrypt the IV (and save the current one) */
|
||||
memcpy( c->lastiv, c->iv, STD_BLOCKSIZE );
|
||||
(*c->encrypt)( &c->context, c->iv, c->iv );
|
||||
/* XOR the input with the IV and store input into IV */
|
||||
for(ivp=c->iv,i=0; i < STD_BLOCKSIZE; i++ ) {
|
||||
temp = *inbuf++;
|
||||
*outbuf++ = *ivp ^ temp;
|
||||
*ivp++ = temp;
|
||||
}
|
||||
nbytes -= STD_BLOCKSIZE;
|
||||
}
|
||||
#ifdef BIG_ENDIAN_HOST
|
||||
}
|
||||
#endif
|
||||
if( nbytes ) { /* process the remaining bytes */
|
||||
/* encrypt the IV (and save the current one) */
|
||||
memcpy( c->lastiv, c->iv, STD_BLOCKSIZE );
|
||||
memcpy( c->lastiv, c->iv, blocksize );
|
||||
(*c->encrypt)( &c->context, c->iv, c->iv );
|
||||
c->unused = STD_BLOCKSIZE;
|
||||
c->unused = blocksize;
|
||||
/* and apply the xor */
|
||||
c->unused -= nbytes;
|
||||
for(ivp=c->iv; nbytes; nbytes-- ) {
|
||||
@ -576,8 +554,8 @@ void
|
||||
cipher_sync( CIPHER_HANDLE c )
|
||||
{
|
||||
if( c->mode == CIPHER_MODE_PHILS_CFB && c->unused ) {
|
||||
memmove(c->iv + c->unused, c->iv, STD_BLOCKSIZE - c->unused );
|
||||
memcpy(c->iv, c->lastiv + STD_BLOCKSIZE - c->unused, 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;
|
||||
}
|
||||
}
|
||||
|
@ -939,7 +939,6 @@ gnupgext_enum_func( int what, int *sequence, int *class, int *vers )
|
||||
void *ret;
|
||||
int i = *sequence;
|
||||
|
||||
/*log_info("gnupgext_enum_func in rsa+idea called what=%d i=%d: ", what, i);*/
|
||||
do {
|
||||
if( i >= DIM(func_table) || i < 0 ) {
|
||||
/*fprintf(stderr, "failed\n");*/
|
||||
|
45
doc/DETAILS
45
doc/DETAILS
@ -56,23 +56,18 @@ Record type 1:
|
||||
--------------
|
||||
Version information for this TrustDB. This is always the first
|
||||
record of the DB and the only one with type 1.
|
||||
1 byte value 2
|
||||
1 byte value 1
|
||||
3 bytes 'gpg' magic value
|
||||
1 byte Version of the TrustDB
|
||||
3 byte reserved
|
||||
1 u32 locked by (pid) 0 = not locked.
|
||||
1 u32 locked flags
|
||||
1 u32 timestamp of trustdb creation
|
||||
1 u32 timestamp of last modification
|
||||
1 u32 timestamp of last validation
|
||||
(Used to keep track of the time, when this TrustDB was checked
|
||||
against the pubring)
|
||||
1 u32 reserved
|
||||
1 byte marginals needed
|
||||
1 byte completes needed
|
||||
1 byte max. cert depth
|
||||
If any of this 3 values are changed, all cache records
|
||||
must be invalidated.
|
||||
9 bytes reserved
|
||||
1 u32 record number of keyhashtable
|
||||
12 bytes reserved
|
||||
|
||||
|
||||
Record type 2: (directory record)
|
||||
@ -183,9 +178,9 @@ Record type 9: (cache record)
|
||||
|
||||
Record Type 10 (hash table)
|
||||
--------------
|
||||
Due to the fact that we use the keyid to lookup keys, we can
|
||||
Due to the fact that we use fingerprints to lookup keys, we can
|
||||
implement quick access by some simple hash methods, and avoid
|
||||
the overhead of gdbm. A property of keyids is that they can be
|
||||
the overhead of gdbm. A property of fingerprints is that they can be
|
||||
used directly as hash values. (They can be considered as strong
|
||||
random numbers.)
|
||||
What we use is a dynamic multilevel architecture, which combines
|
||||
@ -194,11 +189,11 @@ Record Type 10 (hash table)
|
||||
This record is a hashtable of 256 entries; a special property
|
||||
is that all these records are stored consecutively to make one
|
||||
big table. The hash value is simple the 1st, 2nd, ... byte of
|
||||
the keyid (depending on the indirection level).
|
||||
the fingerprint (depending on the indirection level).
|
||||
|
||||
1 byte value 10
|
||||
1 byte reserved
|
||||
n u32 recnum; n depends on th record length:
|
||||
n u32 recnum; n depends on the record length:
|
||||
n = (reclen-2)/4 which yields 9 for the current record length
|
||||
of 40 bytes.
|
||||
|
||||
@ -206,18 +201,15 @@ Record Type 10 (hash table)
|
||||
m = (256+n-1) / n
|
||||
which is 29 for a record length of 40.
|
||||
|
||||
To look up a key we use its lsb to get the recnum from this
|
||||
hashtable and look up the addressed record:
|
||||
- If this record is another hashtable, we use 2nd lsb
|
||||
To look up a key we use the first byte of the fingerprint to get
|
||||
the recnum from this hashtable and look up the addressed record:
|
||||
- If this record is another hashtable, we use 2nd byte
|
||||
to index this hast table and so on.
|
||||
- if this record is a hashlist, we walk thru the
|
||||
reclist records until we found one whose hash field
|
||||
matches the MSB of our keyid, and lookup this record
|
||||
- if this record is a dir record, we compare the
|
||||
keyid and if this is correct, we get the keyrecod and compare
|
||||
the fingerprint to decide whether it is the requested key;
|
||||
if this is not the correct dir record, we look at the next
|
||||
dir record which is linked by the link field.
|
||||
- if this record is a hashlist, we walk all entries
|
||||
until we found one a matching one.
|
||||
- if this record is a key record, we compare the
|
||||
fingerprint and to decide whether it is the requested key;
|
||||
|
||||
|
||||
Record type 11 (hash list)
|
||||
--------------
|
||||
@ -226,11 +218,10 @@ Record type 11 (hash list)
|
||||
1 byte value 11
|
||||
1 byte reserved
|
||||
1 u32 next next hash list record
|
||||
n times n = (reclen-6)/5
|
||||
1 byte hash
|
||||
n times n = (reclen-5)/5
|
||||
1 u32 recnum
|
||||
|
||||
For the current record length of 40, n is 6
|
||||
For the current record length of 40, n is 7
|
||||
|
||||
|
||||
|
||||
|
69
doc/gpg.1pod
69
doc/gpg.1pod
@ -5,6 +5,7 @@ gpg - GNU Privacy Guard
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<gpg> [--homedir name] [--options file] [options] command [args]
|
||||
|
||||
B<gpgm> [--homedir name] [--options file] [options] command [args]
|
||||
|
||||
=head1 DESCRIPTION
|
||||
@ -98,23 +99,46 @@ B<--gen-key>
|
||||
Generate a new key pair. This command can only be
|
||||
used interactive.
|
||||
|
||||
B<--add-key> I<name>
|
||||
Add a subkey to an already existing key. This
|
||||
command is similiar to B<--gen-key> but a primary
|
||||
key must already exit.
|
||||
|
||||
B<--sign-key> I<name>
|
||||
Make a signature on key of user I<name>.
|
||||
This looks for the key, displays the key and checks
|
||||
all existing signatures of this key. 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>.
|
||||
The key is then signed and the keyring which
|
||||
contains the key is updated.
|
||||
|
||||
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<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<passwd>
|
||||
Change the passphrase of the secret key.
|
||||
B<check>
|
||||
Check signatures
|
||||
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<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.
|
||||
|
||||
B<--delete-key>
|
||||
Remove key from the public keyring
|
||||
@ -122,12 +146,6 @@ B<--delete-key>
|
||||
B<--delete-secret-key>
|
||||
Remove key from the secret and public keyring
|
||||
|
||||
B<--edit-key>
|
||||
Edit/remove a key signature.
|
||||
|
||||
B<--change-passphrase>
|
||||
Change the passphrase of your secret keyring
|
||||
|
||||
B<--gen-revoke>
|
||||
Generate a revocation certificate.
|
||||
|
||||
@ -142,10 +160,15 @@ B<--export> [I<names>]
|
||||
B<--import>
|
||||
import/merge keys
|
||||
|
||||
B<--list-ownertrust>
|
||||
B<--export-ownertrust>
|
||||
List the assigned ownertrust values in ascii format for
|
||||
backup purposes [B<gpgm> only].
|
||||
|
||||
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. [B<gpgm> only].
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
Long options can be put in an options file (default F<~/.gnupg/options>);
|
||||
|
@ -1,3 +1,26 @@
|
||||
Wed Jul 29 12:53:03 1998 Werner Koch (wk@(none))
|
||||
|
||||
* free-packet.c (copy_signature): New.
|
||||
|
||||
* keygen.c (generate_subkeypair): rewritten
|
||||
* g10.c (aKeyadd): Removed option --add-key
|
||||
|
||||
Mon Jul 27 10:37:28 1998 Werner Koch (wk@(none))
|
||||
|
||||
* seckey-cert.c (do_check): Additional check on cipher blocksize.
|
||||
(protect_secret_key): Ditto.
|
||||
* encr-data.c: Support for other blocksizes.
|
||||
* cipher.c (write_header): Ditto.
|
||||
|
||||
Fri Jul 24 16:47:59 1998 Werner Koch (wk@(none))
|
||||
|
||||
* kbnode.c (insert_kbnode): Changed semantics and all callers.
|
||||
* keyedit.c : More or less a complete rewrite
|
||||
|
||||
Wed Jul 22 17:10:04 1998 Werner Koch (wk@(none))
|
||||
|
||||
* build-packet.c (write_sign_packet_header): New.
|
||||
|
||||
Tue Jul 21 14:37:09 1998 Werner Koch (wk@(none))
|
||||
|
||||
* import.c (import_one): Now creates a trustdb record.
|
||||
|
@ -48,7 +48,6 @@ common_source = \
|
||||
status.c \
|
||||
status.h \
|
||||
sign.c \
|
||||
keyedit.c \
|
||||
plaintext.c \
|
||||
encr-data.c \
|
||||
encode.c \
|
||||
@ -61,6 +60,7 @@ gpg_SOURCES = g10.c \
|
||||
$(common_source) \
|
||||
verify.c \
|
||||
decrypt.c \
|
||||
keyedit.c \
|
||||
keygen.c
|
||||
|
||||
|
||||
|
@ -57,3 +57,9 @@ compress-sigs
|
||||
# Normally, compressing of signatures does not make sense; so this
|
||||
# is disabled for detached signatures unless this option is used.
|
||||
|
||||
|
||||
emulate-pgp-sign-bug
|
||||
# PGP 2.x can only cope with 2 byte length headers of the
|
||||
# signature packets, this option forces.
|
||||
|
||||
|
||||
|
@ -51,6 +51,7 @@ static int calc_header_length( u32 len );
|
||||
static int write_16(IOBUF inp, u16 a);
|
||||
static int write_32(IOBUF inp, u32 a);
|
||||
static int write_header( IOBUF out, int ctb, u32 len );
|
||||
static int write_sign_packet_header( IOBUF out, int ctb, u32 len );
|
||||
static int write_header2( IOBUF out, int ctb, u32 len, int hdrlen, int blkmode );
|
||||
static int write_new_header( IOBUF out, int ctb, u32 len, int hdrlen );
|
||||
static int write_version( IOBUF out, int ctb );
|
||||
@ -669,7 +670,10 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
|
||||
for(i=0; i < n; i++ )
|
||||
mpi_write(a, sig->data[i] );
|
||||
|
||||
write_header(out, ctb, iobuf_get_temp_length(a) );
|
||||
if( is_RSA(sig->pubkey_algo) && sig->version < 4 )
|
||||
write_sign_packet_header(out, ctb, iobuf_get_temp_length(a) );
|
||||
else
|
||||
write_header(out, ctb, iobuf_get_temp_length(a) );
|
||||
if( iobuf_write_temp( out, a ) )
|
||||
rc = G10ERR_WRITE_FILE;
|
||||
|
||||
@ -747,6 +751,18 @@ write_header( IOBUF out, int ctb, u32 len )
|
||||
return write_header2( out, ctb, len, 0, 1 );
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
write_sign_packet_header( IOBUF out, int ctb, u32 len )
|
||||
{
|
||||
/* work around a bug in the pgp read function for signature packets,
|
||||
* which are not correctly coded and silently assume at some
|
||||
* point 2 byte length headers.*/
|
||||
iobuf_put(out, 0x89 );
|
||||
iobuf_put(out, len >> 8 );
|
||||
return iobuf_put(out, len ) == -1 ? -1:0;
|
||||
}
|
||||
|
||||
/****************
|
||||
* if HDRLEN is > 0, try to build a header of this length.
|
||||
* we need this, so that we can hash packets without reading them again.
|
||||
|
16
g10/cipher.c
16
g10/cipher.c
@ -42,7 +42,8 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
|
||||
{
|
||||
PACKET pkt;
|
||||
PKT_encrypted ed;
|
||||
byte temp[10];
|
||||
byte temp[18];
|
||||
unsigned blocksize;
|
||||
|
||||
memset( &ed, 0, sizeof ed );
|
||||
ed.len = cfx->datalen;
|
||||
@ -52,15 +53,18 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
|
||||
pkt.pkt.encrypted = &ed;
|
||||
if( build_packet( a, &pkt ))
|
||||
log_bug("build_packet(ENCR_DATA) failed\n");
|
||||
randomize_buffer( temp, 8, 1 );
|
||||
temp[8] = temp[6];
|
||||
temp[9] = temp[7];
|
||||
blocksize = cipher_get_blocksize( cfx->dek->algo );
|
||||
if( blocksize < 8 || blocksize > 16 )
|
||||
log_fatal("unsupported blocksize %u\n", blocksize );
|
||||
randomize_buffer( temp, blocksize, 1 );
|
||||
temp[blocksize] = temp[blocksize-2];
|
||||
temp[blocksize+1] = temp[blocksize-1];
|
||||
cfx->cipher_hd = cipher_open( cfx->dek->algo, CIPHER_MODE_AUTO_CFB, 1 );
|
||||
cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen );
|
||||
cipher_setiv( cfx->cipher_hd, NULL );
|
||||
cipher_encrypt( cfx->cipher_hd, temp, temp, 10);
|
||||
cipher_encrypt( cfx->cipher_hd, temp, temp, blocksize+2);
|
||||
cipher_sync( cfx->cipher_hd );
|
||||
iobuf_write(a, temp, 10);
|
||||
iobuf_write(a, temp, blocksize+2);
|
||||
cfx->header=1;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,8 @@ decrypt_data( PKT_encrypted *ed, DEK *dek )
|
||||
decode_filter_ctx_t dfx;
|
||||
byte *p;
|
||||
int rc, c, i;
|
||||
byte temp[16];
|
||||
byte temp[32];
|
||||
unsigned blocksize;
|
||||
|
||||
if( opt.verbose ) {
|
||||
const char *s = cipher_algo_to_string( dek->algo );
|
||||
@ -60,7 +61,10 @@ decrypt_data( PKT_encrypted *ed, DEK *dek )
|
||||
}
|
||||
if( (rc=check_cipher_algo(dek->algo)) )
|
||||
return rc;
|
||||
if( ed->len && ed->len < 10 )
|
||||
blocksize = cipher_get_blocksize(dek->algo);
|
||||
if( !blocksize || blocksize > 16 )
|
||||
log_fatal("unsupported blocksize %u\n", blocksize );
|
||||
if( ed->len && ed->len < (blocksize+2) )
|
||||
log_bug("Nanu\n"); /* oops: found a bug */
|
||||
|
||||
dfx.cipher_hd = cipher_open( dek->algo, CIPHER_MODE_AUTO_CFB, 1 );
|
||||
@ -70,20 +74,20 @@ decrypt_data( PKT_encrypted *ed, DEK *dek )
|
||||
if( ed->len ) {
|
||||
iobuf_set_limit( ed->buf, ed->len );
|
||||
|
||||
for(i=0; i < 10 && ed->len; i++, ed->len-- )
|
||||
for(i=0; i < (blocksize+2) && ed->len; i++, ed->len-- )
|
||||
temp[i] = iobuf_get(ed->buf);
|
||||
}
|
||||
else {
|
||||
for(i=0; i < 10; i++ )
|
||||
for(i=0; i < (blocksize+2); i++ )
|
||||
if( (c=iobuf_get(ed->buf)) == -1 )
|
||||
break;
|
||||
else
|
||||
temp[i] = c;
|
||||
}
|
||||
cipher_decrypt( dfx.cipher_hd, temp, temp, 10);
|
||||
cipher_decrypt( dfx.cipher_hd, temp, temp, blocksize+2);
|
||||
cipher_sync( dfx.cipher_hd );
|
||||
p = temp;
|
||||
if( p[6] != p[8] || p[7] != p[9] ) {
|
||||
if( p[blocksize-2] != p[blocksize] || p[blocksize-1] != p[blocksize+1] ) {
|
||||
cipher_close(dfx.cipher_hd);
|
||||
return G10ERR_BAD_KEY;
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ void
|
||||
free_seckey_enc( PKT_signature *sig )
|
||||
{
|
||||
int n, i;
|
||||
n = pubkey_get_nenc( sig->pubkey_algo );
|
||||
n = pubkey_get_nsig( sig->pubkey_algo );
|
||||
if( !n ) {
|
||||
m_free(sig->data[0]);
|
||||
sig->data[0] = NULL;
|
||||
@ -107,6 +107,20 @@ cp_fake_data( MPI a )
|
||||
return d;
|
||||
}
|
||||
|
||||
static void *
|
||||
cp_data_block( byte *s )
|
||||
{
|
||||
byte *d;
|
||||
u16 len;
|
||||
|
||||
if( !s )
|
||||
return NULL;
|
||||
len = (s[0] << 8) | s[1];
|
||||
d = m_alloc( len+2 );
|
||||
memcpy(d, s, len+2);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
PKT_public_key *
|
||||
copy_public_key( PKT_public_key *d, PKT_public_key *s )
|
||||
@ -126,6 +140,39 @@ copy_public_key( PKT_public_key *d, PKT_public_key *s )
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
PKT_signature *
|
||||
copy_signature( PKT_signature *d, PKT_signature *s )
|
||||
{
|
||||
int n, i;
|
||||
|
||||
if( !d )
|
||||
d = m_alloc(sizeof *d);
|
||||
memcpy( d, s, sizeof *d );
|
||||
n = pubkey_get_nsig( s->pubkey_algo );
|
||||
if( !n )
|
||||
d->data[0] = cp_fake_data(s->data[0]);
|
||||
else {
|
||||
for(i=0; i < n; i++ )
|
||||
d->data[i] = mpi_copy( s->data[i] );
|
||||
}
|
||||
d->hashed_data = cp_data_block(s->hashed_data);
|
||||
d->unhashed_data = cp_data_block(s->unhashed_data);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
PKT_user_id *
|
||||
copy_user_id( PKT_user_id *d, PKT_user_id *s )
|
||||
{
|
||||
if( !d )
|
||||
d = m_alloc(sizeof *d + s->len - 1 );
|
||||
memcpy( d, s, sizeof *d + s->len - 1 );
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
release_secret_key_parts( PKT_secret_key *sk )
|
||||
{
|
||||
|
69
g10/g10.c
69
g10/g10.c
@ -68,11 +68,8 @@ static ARGPARSE_OPTS opts[] = {
|
||||
{ 558, "list-secret-keys", 256, N_("list secret keys")},
|
||||
#ifdef IS_G10
|
||||
{ 503, "gen-key", 256, N_("generate a new key pair")},
|
||||
{ 554, "add-key", 256, N_("add a subkey to a key pair")},
|
||||
{ 506, "sign-key" ,256, N_("make a signature on a key in the keyring")},
|
||||
{ 505, "delete-key",256, N_("remove key from the public keyring")},
|
||||
{ 524, "edit-key" ,256, N_("edit a key signature")},
|
||||
{ 525, "change-passphrase", 256, N_("change the passphrase of your secret keyring")},
|
||||
{ 524, "edit-key" ,256, N_("sign or edit a key")},
|
||||
{ 542, "gen-revoke",256, N_("generate a revocation certificate")},
|
||||
#endif
|
||||
{ 537, "export" , 256, N_("export keys") },
|
||||
@ -81,7 +78,8 @@ static ARGPARSE_OPTS opts[] = {
|
||||
{ 530, "import", 256 , N_("import/merge keys")},
|
||||
{ 521, "list-packets",256,N_("list only the sequence of packets")},
|
||||
#ifdef IS_G10MAINT
|
||||
{ 564, "list-ownertrust", 256, N_("list the ownertrust values")},
|
||||
{ 564, "export-ownertrust", 256, N_("export the ownertrust values")},
|
||||
{ 525, "import-ownertrust", 256 , N_("import ownertrust values")},
|
||||
{ 567, "check-trustdb",0 , N_("|[NAMES]|check the trust database")},
|
||||
{ 546, "dearmor", 256, N_("De-Armor a file or stdin") },
|
||||
{ 547, "enarmor", 256, N_("En-Armor a file or stdin") },
|
||||
@ -153,6 +151,7 @@ static ARGPARSE_OPTS opts[] = {
|
||||
{ 504, "delete-secret-key",0, "@" },
|
||||
{ 524, "edit-sig" ,0, "@"}, /* alias for edit-key */
|
||||
{ 523, "passphrase-fd",1, "@" },
|
||||
{ 506, "sign-key" ,256, "@" }, /* alias for edit-key */
|
||||
#endif
|
||||
{ 532, "quick-random", 0, "@"},
|
||||
{ 526, "no-verbose", 0, "@"},
|
||||
@ -173,18 +172,18 @@ static ARGPARSE_OPTS opts[] = {
|
||||
{ 566, "compress-sigs",0, "@"},
|
||||
{ 559, "always-trust", 0, "@"},
|
||||
{ 562, "emulate-checksum-bug", 0, "@"},
|
||||
|
||||
/*554 is unused */
|
||||
{0} };
|
||||
|
||||
|
||||
enum cmd_values { aNull = 0,
|
||||
aSym, aStore, aEncr, aKeygen, aSign, aSignEncr,
|
||||
aSignKey, aClearsign, aListPackets, aEditKey, aDeleteKey, aDeleteSecretKey,
|
||||
aKMode, aKModeC, aChangePass, aImport, aVerify, aDecrypt, aListKeys,
|
||||
aListSigs, aKeyadd, aListSecretKeys,
|
||||
aExport, aExportSecret,
|
||||
aKMode, aKModeC, aImport, aVerify, aDecrypt, aListKeys,
|
||||
aListSigs, aListSecretKeys, aExport, aExportSecret,
|
||||
aCheckKeys, aGenRevoke, aPrimegen, aPrintMD, aPrintMDs,
|
||||
aCheckTrustDB, aListTrustDB, aListTrustPath, aListOwnerTrust,
|
||||
aCheckTrustDB, aListTrustDB, aListTrustPath,
|
||||
aExportOwnerTrust, aImportOwnerTrust,
|
||||
aDeArmor, aEnArmor, aGenRandom,
|
||||
aTest };
|
||||
|
||||
@ -521,7 +520,6 @@ main( int argc, char **argv )
|
||||
case 507: set_cmd( &cmd, aStore); break;
|
||||
case 523: set_passphrase_fd( pargs.r.ret_int ); break;
|
||||
case 524: set_cmd( &cmd, aEditKey); break;
|
||||
case 525: set_cmd( &cmd, aChangePass); break;
|
||||
case 527: def_cipher_string = m_strdup(pargs.r.ret_str); break;
|
||||
case 529: def_digest_string = m_strdup(pargs.r.ret_str); break;
|
||||
case 539: set_cmd( &cmd, aClearsign); break;
|
||||
@ -548,7 +546,8 @@ main( int argc, char **argv )
|
||||
case 546: set_cmd( &cmd, aDeArmor); break;
|
||||
case 547: set_cmd( &cmd, aEnArmor); break;
|
||||
case 555: set_cmd( &cmd, aPrintMD); break;
|
||||
case 564: set_cmd( &cmd, aListOwnerTrust); break;
|
||||
case 564: set_cmd( &cmd, aExportOwnerTrust); break;
|
||||
case 525: set_cmd( &cmd, aImportOwnerTrust); break;
|
||||
#endif /* IS_G10MAINT */
|
||||
|
||||
case 'o': opt.outfile = pargs.r.ret_str; break;
|
||||
@ -564,7 +563,7 @@ main( int argc, char **argv )
|
||||
case 510: opt.debug |= pargs.r.ret_ulong; break;
|
||||
case 511: opt.debug = ~0; break;
|
||||
case 512: set_status_fd( pargs.r.ret_int ); break;
|
||||
case 515: opt.fingerprint = 1; break;
|
||||
case 515: opt.fingerprint++; break;
|
||||
case 517: append_to_strlist( &sec_nrings, pargs.r.ret_str); break;
|
||||
case 518:
|
||||
/* config files may not be nested (silently ignore them) */
|
||||
@ -595,17 +594,17 @@ main( int argc, char **argv )
|
||||
case 551: set_cmd( &cmd, aListKeys); break;
|
||||
case 552: set_cmd( &cmd, aListSigs); break;
|
||||
case 553: opt.skip_verify=1; break;
|
||||
case 554: set_cmd( &cmd, aKeyadd); break;
|
||||
case 556: opt.def_compress_algo = pargs.r.ret_int; break;
|
||||
case 557: opt.compress_keys = 1; break;
|
||||
case 558: set_cmd( &cmd, aListSecretKeys); break;
|
||||
case 559: opt.always_trust = 1; break;
|
||||
case 560: register_cipher_extension(pargs.r.ret_str); break;
|
||||
case 561: opt.rfc1991 = 1; break;
|
||||
case 562: opt.emulate_bugs |= 1; break;
|
||||
case 561: opt.rfc1991 = 1; opt.no_comment = 1; break;
|
||||
case 562: opt.emulate_bugs |= EMUBUG_GPGCHKSUM; break;
|
||||
case 563: set_cmd( &cmd, aExportSecret); break;
|
||||
case 565: opt.do_not_export_rsa = 1; break;
|
||||
case 566: opt.compress_sigs = 1; break;
|
||||
case 554:
|
||||
default : errors++; pargs.err = configfp? 1:2; break;
|
||||
}
|
||||
}
|
||||
@ -722,7 +721,7 @@ main( int argc, char **argv )
|
||||
if( opt.with_colons ) /* need this to list the trust */
|
||||
rc = init_trustdb(1, trustdb_name );
|
||||
break;
|
||||
case aListOwnerTrust: rc = init_trustdb( 0, trustdb_name ); break;
|
||||
case aExportOwnerTrust: rc = init_trustdb( 0, trustdb_name ); break;
|
||||
case aListTrustDB: rc = init_trustdb( argc? 1:0, trustdb_name ); break;
|
||||
default: rc = init_trustdb(1, trustdb_name ); break;
|
||||
}
|
||||
@ -808,19 +807,10 @@ main( int argc, char **argv )
|
||||
|
||||
|
||||
case aSignKey: /* sign the key given as argument */
|
||||
if( argc != 1 )
|
||||
wrong_args(_("--sign-key username"));
|
||||
/* note: fname is the user id! */
|
||||
if( (rc = sign_key(fname, locusr)) )
|
||||
log_error("%s: sign key failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
|
||||
break;
|
||||
|
||||
case aEditKey: /* Edit a key signature */
|
||||
if( argc != 1 )
|
||||
wrong_args(_("--edit-key username"));
|
||||
/* note: fname is the user id! */
|
||||
if( (rc = edit_keysigs(fname)) )
|
||||
log_error("%s: edit signature failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
|
||||
keyedit_menu(fname, locusr );
|
||||
break;
|
||||
|
||||
case aDeleteSecretKey:
|
||||
@ -834,14 +824,6 @@ main( int argc, char **argv )
|
||||
log_error("%s: delete key failed: %s\n", print_fname_stdin(fname), g10_errstr(rc) );
|
||||
break;
|
||||
|
||||
case aChangePass: /* Change the passphrase */
|
||||
if( argc > 1 ) /* no arg: use default, 1 arg use this one */
|
||||
wrong_args(_("--change-passphrase [username]"));
|
||||
/* note: fname is the user id! */
|
||||
if( (rc = change_passphrase(fname)) )
|
||||
log_error("%s: change passphrase failed: %s\n", print_fname_stdin(fname),
|
||||
g10_errstr(rc) );
|
||||
break;
|
||||
#endif /* IS_G10 */
|
||||
|
||||
case aCheckKeys:
|
||||
@ -880,11 +862,6 @@ main( int argc, char **argv )
|
||||
wrong_args("--gen-key");
|
||||
generate_keypair();
|
||||
break;
|
||||
case aKeyadd: /* add a subkey (interactive) */
|
||||
if( argc != 1 )
|
||||
wrong_args("--add-key userid");
|
||||
generate_subkeypair(*argv);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case aImport:
|
||||
@ -1049,10 +1026,16 @@ main( int argc, char **argv )
|
||||
list_trust_path( atoi(*argv), argv[1] );
|
||||
break;
|
||||
|
||||
case aListOwnerTrust:
|
||||
case aExportOwnerTrust:
|
||||
if( argc )
|
||||
wrong_args("--list-ownertrust");
|
||||
list_ownertrust();
|
||||
wrong_args("--export-ownertrust");
|
||||
export_ownertrust();
|
||||
break;
|
||||
|
||||
case aImportOwnerTrust:
|
||||
if( argc > 1 )
|
||||
wrong_args("--import-ownertrust [file]");
|
||||
import_ownertrust( argc? *argv:NULL );
|
||||
break;
|
||||
|
||||
#endif /* IS_G10MAINT */
|
||||
|
@ -851,7 +851,7 @@ merge_sigs( KBNODE dst, KBNODE src, int *n_sigs,
|
||||
* We add a clone to the original keyblock, because this
|
||||
* one is released first */
|
||||
n2 = clone_kbnode(n);
|
||||
insert_kbnode( dst, n2, PKT_USER_ID );
|
||||
insert_kbnode( dst, n2, PKT_SIGNATURE );
|
||||
n2->flag |= 1;
|
||||
n->flag |= 1;
|
||||
++*n_sigs;
|
||||
|
@ -94,7 +94,8 @@ add_kbnode( KBNODE root, KBNODE node )
|
||||
}
|
||||
|
||||
/****************
|
||||
* Insert NODE into the list after root but before a packet with type PKTTYPE
|
||||
* Insert NODE into the list after root but before a packet which is not of
|
||||
* type PKTTYPE
|
||||
* (only if PKTTYPE != 0)
|
||||
*/
|
||||
void
|
||||
@ -108,7 +109,7 @@ insert_kbnode( KBNODE root, KBNODE node, int pkttype )
|
||||
KBNODE n1;
|
||||
|
||||
for(n1=root; n1->next; n1 = n1->next)
|
||||
if( pkttype == n1->next->pkt->pkttype ) {
|
||||
if( pkttype != n1->next->pkt->pkttype ) {
|
||||
node->next = n1->next;
|
||||
n1->next = node;
|
||||
return;
|
||||
|
@ -133,6 +133,8 @@ unsigned nbits_from_sk( PKT_secret_key *sk );
|
||||
const char *datestr_from_pk( PKT_public_key *pk );
|
||||
const char *datestr_from_sk( PKT_secret_key *sk );
|
||||
const char *datestr_from_sig( PKT_signature *sig );
|
||||
const char *expirestr_from_pk( PKT_public_key *pk );
|
||||
const char *expirestr_from_sk( PKT_secret_key *sk );
|
||||
byte *fingerprint_from_sk( PKT_secret_key *sk, byte *buf, size_t *ret_len );
|
||||
byte *fingerprint_from_pk( PKT_public_key *pk, byte *buf, size_t *ret_len );
|
||||
|
||||
@ -149,6 +151,7 @@ KBNODE find_kbnode( KBNODE node, int pkttype );
|
||||
KBNODE walk_kbnode( KBNODE root, KBNODE *context, int all );
|
||||
void clear_kbnode_flags( KBNODE n );
|
||||
int commit_kbnode( KBNODE *root );
|
||||
void dump_kbnode( KBNODE node );
|
||||
|
||||
/*-- ringedit.c --*/
|
||||
int add_keyblock_resource( const char *filename, int force, int secret );
|
||||
|
1444
g10/keyedit.c
1444
g10/keyedit.c
File diff suppressed because it is too large
Load Diff
169
g10/keygen.c
169
g10/keygen.c
@ -74,8 +74,8 @@ add_key_expire( PKT_signature *sig, void *opaque )
|
||||
* Add preference to the self signature packet.
|
||||
* This is only called for packets with version > 3.
|
||||
*/
|
||||
static int
|
||||
add_prefs( PKT_signature *sig, void *opaque )
|
||||
int
|
||||
keygen_add_std_prefs( PKT_signature *sig, void *opaque )
|
||||
{
|
||||
byte buf[8];
|
||||
|
||||
@ -134,7 +134,7 @@ write_selfsig( KBNODE root, KBNODE pub_root, PKT_secret_key *sk )
|
||||
|
||||
/* and make the signature */
|
||||
rc = make_keysig_packet( &sig, pk, uid, NULL, sk, 0x13, 0,
|
||||
add_prefs, sk );
|
||||
keygen_add_std_prefs, sk );
|
||||
if( rc ) {
|
||||
log_error("make_keysig_packet failed: %s\n", g10_errstr(rc) );
|
||||
return rc;
|
||||
@ -444,25 +444,18 @@ ask_keysize( int algo )
|
||||
else if( nbits > 2048 ) {
|
||||
tty_printf(_("Keysizes larger than 2048 are not suggested because "
|
||||
"computations take REALLY long!\n"));
|
||||
answer = tty_get(_("Are you sure that you want this keysize? "));
|
||||
tty_kill_prompt();
|
||||
if( answer_is_yes(answer) ) {
|
||||
m_free(answer);
|
||||
if( tty_get_answer_is_yes(_(
|
||||
"Are you sure that you want this keysize? ")) ) {
|
||||
tty_printf(_("Okay, but keep in mind that your monitor "
|
||||
"and keyboard radiation is also very vulnerable "
|
||||
"to attacks!\n"));
|
||||
break;
|
||||
}
|
||||
m_free(answer);
|
||||
}
|
||||
else if( nbits > 1536 ) {
|
||||
answer = tty_get(_("Do you really need such a large keysize? "));
|
||||
tty_kill_prompt();
|
||||
if( answer_is_yes(answer) ) {
|
||||
m_free(answer);
|
||||
if( tty_get_answer_is_yes(_(
|
||||
"Do you really need such a large keysize? ")) )
|
||||
break;
|
||||
}
|
||||
m_free(answer);
|
||||
}
|
||||
else
|
||||
break;
|
||||
@ -524,10 +517,7 @@ ask_valid_days()
|
||||
add_days_to_timestamp( make_timestamp(), valid_days )));
|
||||
}
|
||||
|
||||
m_free(answer);
|
||||
answer = tty_get(_("Is this correct (y/n)? "));
|
||||
tty_kill_prompt();
|
||||
if( answer_is_yes(answer) )
|
||||
if( tty_get_answer_is_yes(_("Is this correct (y/n)? ")) )
|
||||
break;
|
||||
}
|
||||
m_free(answer);
|
||||
@ -549,12 +539,13 @@ has_invalid_email_chars( const char *s )
|
||||
|
||||
|
||||
static char *
|
||||
ask_user_id()
|
||||
ask_user_id( int mode )
|
||||
{
|
||||
char *answer;
|
||||
char *aname, *acomment, *amail, *uid;
|
||||
|
||||
tty_printf( _("\n"
|
||||
if( !mode )
|
||||
tty_printf( _("\n"
|
||||
"You need a User-ID to identify your key; the software constructs the user id\n"
|
||||
"from Real Name, Comment and Email Address in this form:\n"
|
||||
" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n\n") );
|
||||
@ -630,28 +621,37 @@ ask_user_id()
|
||||
tty_printf(_("You selected this USER-ID:\n \"%s\"\n\n"), uid);
|
||||
/* fixme: add a warning if this user-id already exists */
|
||||
for(;;) {
|
||||
answer = tty_get(_("Edit (N)ame, (C)omment, (E)mail or (O)kay? "));
|
||||
char *ansstr = N_("NnCcEeOoQq");
|
||||
answer = tty_get(_(
|
||||
"Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? "));
|
||||
tty_kill_prompt();
|
||||
if( strlen(answer) > 1 )
|
||||
;
|
||||
else if( *answer == 'N' || *answer == 'n' ) {
|
||||
else if( *answer == ansstr[0] || *answer == ansstr[1] ) {
|
||||
m_free(aname); aname = NULL;
|
||||
break;
|
||||
}
|
||||
else if( *answer == 'C' || *answer == 'c' ) {
|
||||
else if( *answer == ansstr[2] || *answer == ansstr[3] ) {
|
||||
m_free(acomment); acomment = NULL;
|
||||
break;
|
||||
}
|
||||
else if( *answer == 'E' || *answer == 'e' ) {
|
||||
else if( *answer == ansstr[4] || *answer == ansstr[5] ) {
|
||||
m_free(amail); amail = NULL;
|
||||
break;
|
||||
}
|
||||
else if( *answer == 'O' || *answer == 'o' ) {
|
||||
else if( *answer == ansstr[6] || *answer == ansstr[7] ) {
|
||||
m_free(aname); aname = NULL;
|
||||
m_free(acomment); acomment = NULL;
|
||||
m_free(amail); amail = NULL;
|
||||
break;
|
||||
}
|
||||
else if( *answer == ansstr[8] || *answer == ansstr[9] ) {
|
||||
m_free(aname); aname = NULL;
|
||||
m_free(acomment); acomment = NULL;
|
||||
m_free(amail); amail = NULL;
|
||||
m_free(uid); uid = NULL;
|
||||
break;
|
||||
}
|
||||
m_free(answer);
|
||||
}
|
||||
m_free(answer);
|
||||
@ -685,7 +685,7 @@ ask_passphrase( STRING2KEY **ret_s2k )
|
||||
tty_printf(_(
|
||||
"You don't want a passphrase - this is probably a *bad* idea!\n"
|
||||
"I will do it anyway. You can change your passphrase at any time,\n"
|
||||
"using this program with the option \"--change-passphrase\".\n\n"));
|
||||
"using this program with the option \"--edit-key\".\n\n"));
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -728,6 +728,27 @@ do_create( int algo, unsigned nbits, KBNODE pub_root, KBNODE sec_root,
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Generate a new user id packet, or return NULL if cancelled
|
||||
*/
|
||||
PKT_user_id *
|
||||
generate_user_id()
|
||||
{
|
||||
PKT_user_id *uid;
|
||||
char *p;
|
||||
size_t n;
|
||||
|
||||
p = ask_user_id( 1 );
|
||||
if( !p )
|
||||
return NULL;
|
||||
n = strlen(p);
|
||||
uid = m_alloc( sizeof *uid + n - 1 );
|
||||
uid->len = n;
|
||||
strcpy(uid->name, p);
|
||||
return uid;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Generate a keypair
|
||||
*/
|
||||
@ -762,7 +783,11 @@ generate_keypair()
|
||||
}
|
||||
nbits = ask_keysize( algo );
|
||||
ndays = ask_valid_days();
|
||||
uid = ask_user_id();
|
||||
uid = ask_user_id(0);
|
||||
if( !uid ) {
|
||||
log_error(_("Key generation cancelled.\n"));
|
||||
return;
|
||||
}
|
||||
dek = ask_passphrase( &s2k );
|
||||
|
||||
|
||||
@ -879,88 +904,29 @@ generate_keypair()
|
||||
|
||||
/****************
|
||||
* add a new subkey to an existing key.
|
||||
* Returns true if a new key has been generated and put into the keyblocks.
|
||||
*/
|
||||
void
|
||||
generate_subkeypair( const char *username )
|
||||
int
|
||||
generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock )
|
||||
{
|
||||
int rc=0;
|
||||
KBPOS pub_kbpos, sec_kbpos;
|
||||
KBNODE pub_keyblock = NULL;
|
||||
KBNODE sec_keyblock = NULL;
|
||||
int okay=0, rc=0;
|
||||
KBNODE node;
|
||||
PKT_secret_key *sk = NULL; /* this is the primary sk */
|
||||
u32 keyid[2];
|
||||
int v4, algo, ndays;
|
||||
unsigned nbits;
|
||||
char *passphrase = NULL;
|
||||
DEK *dek = NULL;
|
||||
STRING2KEY *s2k = NULL;
|
||||
|
||||
if( opt.batch || opt.answer_yes || opt.answer_no ) {
|
||||
log_error(_("Key generation can only be used in interactive mode\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
/* search the userid */
|
||||
rc = find_secret_keyblock_byname( &sec_kbpos, username );
|
||||
if( rc ) {
|
||||
log_error("user '%s' not found\n", username );
|
||||
goto leave;
|
||||
}
|
||||
rc = read_keyblock( &sec_kbpos, &sec_keyblock );
|
||||
if( rc ) {
|
||||
log_error("error reading the secret key: %s\n", g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
/* and the public key */
|
||||
rc = find_keyblock_byname( &pub_kbpos, username );
|
||||
if( rc ) {
|
||||
log_error("user '%s' not found in public ring\n", username );
|
||||
goto leave;
|
||||
}
|
||||
rc = read_keyblock( &pub_kbpos, &pub_keyblock );
|
||||
if( rc ) {
|
||||
log_error("error reading the public key: %s\n", g10_errstr(rc) );
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* break out the primary key */
|
||||
/* break out the primary secret key */
|
||||
node = find_kbnode( sec_keyblock, PKT_SECRET_KEY );
|
||||
if( !node ) {
|
||||
log_error("Oops; secret key not found anymore!\n");
|
||||
rc = G10ERR_GENERAL;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* make a copy of the sk to keep the protected one in the keyblock */
|
||||
sk = copy_secret_key( NULL, node->pkt->pkt.secret_key );
|
||||
keyid_from_sk( sk, keyid );
|
||||
/* display primary and all secondary keys */
|
||||
tty_printf("sec %4u%c/%08lX %s ",
|
||||
nbits_from_sk( sk ),
|
||||
pubkey_letter( sk->pubkey_algo ),
|
||||
keyid[1], datestr_from_sk(sk) );
|
||||
{
|
||||
size_t n;
|
||||
char *p = get_user_id( keyid, &n );
|
||||
tty_print_string( p, n );
|
||||
m_free(p);
|
||||
tty_printf("\n");
|
||||
}
|
||||
for(node=sec_keyblock; node; node = node->next ) {
|
||||
if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
|
||||
PKT_secret_key *subsk = node->pkt->pkt.secret_key;
|
||||
keyid_from_sk( subsk, keyid );
|
||||
tty_printf("sub %4u%c/%08lX %s\n",
|
||||
nbits_from_sk( subsk ),
|
||||
pubkey_letter( subsk->pubkey_algo ),
|
||||
keyid[1], datestr_from_sk(subsk) );
|
||||
}
|
||||
}
|
||||
tty_printf("\n");
|
||||
|
||||
|
||||
|
||||
/* unprotect to get the passphrase */
|
||||
switch( is_secret_key_protected( sk ) ) {
|
||||
case -1:
|
||||
@ -984,6 +950,8 @@ generate_subkeypair( const char *username )
|
||||
assert(algo);
|
||||
nbits = ask_keysize( algo );
|
||||
ndays = ask_valid_days();
|
||||
if( !tty_get_answer_is_yes( _("Really create? ") ) )
|
||||
goto leave;
|
||||
|
||||
if( passphrase ) {
|
||||
s2k = m_alloc_secure( sizeof *s2k );
|
||||
@ -999,31 +967,18 @@ generate_subkeypair( const char *username )
|
||||
rc = write_keybinding(pub_keyblock, pub_keyblock, sk);
|
||||
if( !rc )
|
||||
rc = write_keybinding(sec_keyblock, pub_keyblock, sk);
|
||||
/* write back */
|
||||
if( !rc ) {
|
||||
rc = update_keyblock( &pub_kbpos, pub_keyblock );
|
||||
if( rc )
|
||||
log_error("update_public_keyblock failed\n" );
|
||||
}
|
||||
if( !rc ) {
|
||||
rc = update_keyblock( &sec_kbpos, sec_keyblock );
|
||||
if( rc )
|
||||
log_error("update_secret_keyblock failed\n" );
|
||||
}
|
||||
if( !rc )
|
||||
tty_printf(_("public and secret subkey created.\n") );
|
||||
|
||||
okay = 1;
|
||||
|
||||
leave:
|
||||
if( rc )
|
||||
tty_printf(_("Key generation failed: %s\n"), g10_errstr(rc) );
|
||||
log_error(_("Key generation failed: %s\n"), g10_errstr(rc) );
|
||||
m_free( passphrase );
|
||||
m_free( dek );
|
||||
m_free( s2k );
|
||||
if( sk ) /* release the copy of the (now unprotected) secret key */
|
||||
free_secret_key(sk);
|
||||
release_kbnode( sec_keyblock );
|
||||
release_kbnode( pub_keyblock );
|
||||
set_next_passphrase( NULL );
|
||||
return okay;
|
||||
}
|
||||
|
||||
|
31
g10/keyid.c
31
g10/keyid.c
@ -296,6 +296,37 @@ datestr_from_sig( PKT_signature *sig )
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
expirestr_from_pk( PKT_public_key *pk )
|
||||
{
|
||||
static char buffer[11+5];
|
||||
struct tm *tp;
|
||||
time_t atime;
|
||||
|
||||
if( !pk->valid_days )
|
||||
return "never ";
|
||||
atime = add_days_to_timestamp( pk->timestamp, pk->valid_days );
|
||||
tp = gmtime( &atime );
|
||||
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char *
|
||||
expirestr_from_sk( PKT_secret_key *sk )
|
||||
{
|
||||
static char buffer[11+5];
|
||||
struct tm *tp;
|
||||
time_t atime;
|
||||
|
||||
if( !sk->valid_days )
|
||||
return "never ";
|
||||
atime = add_days_to_timestamp( sk->timestamp, sk->valid_days );
|
||||
tp = gmtime( &atime );
|
||||
sprintf(buffer,"%04d-%02d-%02d", 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
/**************** .
|
||||
* Return a byte array with the fingerprint for the given PK/SK
|
||||
* The length of the array is returned in ret_len. Caller must free
|
||||
|
@ -202,6 +202,8 @@ list_one( const char *name, int secret )
|
||||
any = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
keyid_from_pk( pk2, keyid2 );
|
||||
if( opt.with_colons ) {
|
||||
printf("sub:%c:%u:%d:%08lX%08lX:%s:%u:",
|
||||
@ -224,6 +226,8 @@ list_one( const char *name, int secret )
|
||||
pubkey_letter( pk2->pubkey_algo ),
|
||||
(ulong)keyid2[1],
|
||||
datestr_from_pk( pk2 ) );
|
||||
if( opt.fingerprint > 1 )
|
||||
fingerprint( pk2, NULL );
|
||||
}
|
||||
else if( node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
|
||||
u32 keyid2[2];
|
||||
@ -251,6 +255,9 @@ list_one( const char *name, int secret )
|
||||
pubkey_letter( sk2->pubkey_algo ),
|
||||
(ulong)keyid2[1],
|
||||
datestr_from_sk( sk2 ) );
|
||||
if( opt.fingerprint > 1 )
|
||||
fingerprint( NULL, sk2 );
|
||||
|
||||
}
|
||||
else if( opt.list_sigs && node->pkt->pkttype == PKT_SIGNATURE ) {
|
||||
PKT_signature *sig = node->pkt->pkt.signature;
|
||||
|
@ -72,14 +72,13 @@ int clearsign_file( const char *fname, STRLIST locusr, const char *outfile );
|
||||
int check_key_signature( KBNODE root, KBNODE node, int *is_selfsig );
|
||||
|
||||
/*-- keyedit.c --*/
|
||||
int sign_key( const char *username, STRLIST locusr );
|
||||
int edit_keysigs( const char *username );
|
||||
int delete_key( const char *username, int secure );
|
||||
int change_passphrase( const char *username );
|
||||
void keyedit_menu( const char *username, STRLIST locusr );
|
||||
|
||||
/*-- keygen.c --*/
|
||||
void generate_keypair(void);
|
||||
void generate_subkeypair(const char *userid);
|
||||
int keygen_add_std_prefs( PKT_signature *sig, void *opaque );
|
||||
int generate_subkeypair( KBNODE pub_keyblock, KBNODE sec_keyblock );
|
||||
|
||||
/*-- openfile.c --*/
|
||||
int overwrite_filep( const char *fname );
|
||||
|
@ -520,6 +520,8 @@ list_node( CTX c, KBNODE node )
|
||||
}
|
||||
if( !any )
|
||||
putchar('\n');
|
||||
if( !mainkey && opt.fingerprint > 1 )
|
||||
print_fingerprint( pk, NULL );
|
||||
}
|
||||
else if( (mainkey = (node->pkt->pkttype == PKT_SECRET_KEY) )
|
||||
|| node->pkt->pkttype == PKT_SECRET_SUBKEY ) {
|
||||
@ -583,6 +585,8 @@ list_node( CTX c, KBNODE node )
|
||||
}
|
||||
if( !any )
|
||||
putchar('\n');
|
||||
if( !mainkey && opt.fingerprint > 1 )
|
||||
print_fingerprint( NULL, sk );
|
||||
}
|
||||
else if( node->pkt->pkttype == PKT_SIGNATURE ) {
|
||||
PKT_signature *sig = node->pkt->pkt.signature;
|
||||
|
@ -98,7 +98,7 @@ checksum_u16( unsigned n )
|
||||
u16 a;
|
||||
|
||||
a = (n >> 8) & 0xff;
|
||||
if( opt.emulate_bugs & 1 ) {
|
||||
if( opt.emulate_bugs & EMUBUG_GPGCHKSUM ) {
|
||||
a |= n & 0xff;
|
||||
log_debug("csum_u16 emulated for n=%u\n", n);
|
||||
}
|
||||
@ -142,7 +142,7 @@ checksum_mpi( MPI a )
|
||||
* this stored value if it is still available.
|
||||
*/
|
||||
|
||||
if( opt.emulate_bugs & 1 )
|
||||
if( opt.emulate_bugs & EMUBUG_GPGCHKSUM )
|
||||
nbits = 0;
|
||||
else
|
||||
nbits = mpi_get_nbit_info(a);
|
||||
|
@ -50,10 +50,12 @@ struct {
|
||||
int compress_sigs;
|
||||
int always_trust;
|
||||
int rfc1991;
|
||||
unsigned emulate_bugs; /* bug emulation flags */
|
||||
unsigned emulate_bugs; /* bug emulation flags EMUBUG_xxxx */
|
||||
} opt;
|
||||
|
||||
|
||||
#define EMUBUG_GPGCHKSUM 1
|
||||
|
||||
#define DBG_PACKET_VALUE 1 /* debug packet reading/writing */
|
||||
#define DBG_MPI_VALUE 2 /* debug mpi details */
|
||||
#define DBG_CIPHER_VALUE 4 /* debug cipher handling */
|
||||
|
@ -258,7 +258,9 @@ void free_comment( PKT_comment *rem );
|
||||
void free_packet( PACKET *pkt );
|
||||
PKT_public_key *copy_public_key( PKT_public_key *d, PKT_public_key *s );
|
||||
PKT_secret_key *copy_secret_key( PKT_secret_key *d, PKT_secret_key *s );
|
||||
int cmp_public_keys( PKT_public_key *a, PKT_public_key *b );
|
||||
PKT_signature *copy_signature( PKT_signature *d, PKT_signature *s );
|
||||
PKT_user_id *copy_user_id( PKT_user_id *d, PKT_user_id *s );
|
||||
int cmp_public_keys( PKT_public_key *d, PKT_public_key *s );
|
||||
int cmp_public_secret_key( PKT_public_key *pk, PKT_secret_key *sk );
|
||||
int cmp_user_ids( PKT_user_id *a, PKT_user_id *b );
|
||||
|
||||
@ -298,4 +300,7 @@ int make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
|
||||
int (*mksubpkt)(PKT_signature *, void *),
|
||||
void *opaque );
|
||||
|
||||
/*-- keygen.c --*/
|
||||
PKT_user_id *generate_user_id(void);
|
||||
|
||||
#endif /*G10_PACKET_H*/
|
||||
|
@ -349,7 +349,7 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, ulong *retpos,
|
||||
}
|
||||
|
||||
leave:
|
||||
if( rc == -1 && iobuf_error(inp) )
|
||||
if( !rc && iobuf_error(inp) )
|
||||
rc = G10ERR_INV_KEYRING;
|
||||
return rc;
|
||||
}
|
||||
@ -434,7 +434,8 @@ skip_rest( IOBUF inp, unsigned long pktlen )
|
||||
}
|
||||
else {
|
||||
for( ; pktlen; pktlen-- )
|
||||
iobuf_get(inp);
|
||||
if( iobuf_get(inp) == -1 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1048,6 +1049,7 @@ parse_key( IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
rc = G10ERR_INVALID_PACKET;
|
||||
goto leave;
|
||||
}
|
||||
/* fixme: Add support for other blocksizes */
|
||||
for(i=0; i < 8 && pktlen; i++, pktlen-- )
|
||||
temp[i] = iobuf_get_noeof(inp);
|
||||
if( list_mode ) {
|
||||
|
@ -53,6 +53,8 @@ do_check( PKT_secret_key *sk )
|
||||
BUG();
|
||||
if( check_cipher_algo( sk->protect.algo ) )
|
||||
return G10ERR_CIPHER_ALGO; /* unsupported protection algorithm */
|
||||
if( cipher_get_blocksize( sk->protect.algo ) != 8 )
|
||||
return G10ERR_CIPHER_ALGO; /* unsupported protection algorithm */
|
||||
keyid_from_sk( sk, keyid );
|
||||
dek = passphrase_to_dek( keyid, sk->protect.algo,
|
||||
&sk->protect.s2k, 0 );
|
||||
@ -76,7 +78,7 @@ do_check( PKT_secret_key *sk )
|
||||
csum += checksum_mpi( sk->skey[i] );
|
||||
m_free( buffer );
|
||||
}
|
||||
if( opt.emulate_bugs & 1 ) {
|
||||
if( opt.emulate_bugs & EMUBUG_GPGCHKSUM ) {
|
||||
csum = sk->csum;
|
||||
}
|
||||
cipher_close( cipher_hd );
|
||||
@ -180,6 +182,8 @@ protect_secret_key( PKT_secret_key *sk, DEK *dek )
|
||||
|
||||
if( check_cipher_algo( sk->protect.algo ) )
|
||||
rc = G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
|
||||
else if( cipher_get_blocksize( sk->protect.algo ) != 8 )
|
||||
rc = G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
|
||||
else {
|
||||
cipher_hd = cipher_open( sk->protect.algo,
|
||||
CIPHER_MODE_AUTO_CFB, 1 );
|
||||
|
108
g10/sign.c
108
g10/sign.c
@ -650,4 +650,112 @@ clearsign_file( const char *fname, STRLIST locusr, const char *outfile )
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Create a signature packet for the given public key certificate
|
||||
* and the user id and return it in ret_sig. User signature class SIGCLASS
|
||||
* user-id is not used (and may be NULL if sigclass is 0x20)
|
||||
* If digest_algo is 0 the function selects an appropriate one.
|
||||
*/
|
||||
int
|
||||
make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk,
|
||||
PKT_user_id *uid, PKT_public_key *subpk,
|
||||
PKT_secret_key *sk,
|
||||
int sigclass, int digest_algo,
|
||||
int (*mksubpkt)(PKT_signature *, void *), void *opaque
|
||||
)
|
||||
{
|
||||
PKT_signature *sig;
|
||||
int rc=0;
|
||||
MD_HANDLE md;
|
||||
|
||||
assert( (sigclass >= 0x10 && sigclass <= 0x13)
|
||||
|| sigclass == 0x20 || sigclass == 0x18 );
|
||||
if( !digest_algo ) {
|
||||
switch( sk->pubkey_algo ) {
|
||||
case PUBKEY_ALGO_DSA: digest_algo = DIGEST_ALGO_SHA1; break;
|
||||
case PUBKEY_ALGO_RSA_S:
|
||||
case PUBKEY_ALGO_RSA: digest_algo = DIGEST_ALGO_MD5; break;
|
||||
default: digest_algo = DIGEST_ALGO_RMD160; break;
|
||||
}
|
||||
}
|
||||
md = md_open( digest_algo, 0 );
|
||||
|
||||
/* hash the public key certificate and the user id */
|
||||
hash_public_key( md, pk );
|
||||
if( sigclass == 0x18 ) { /* subkey binding */
|
||||
hash_public_key( md, subpk );
|
||||
}
|
||||
else if( sigclass != 0x20 ) {
|
||||
if( sk->version >=4 ) {
|
||||
byte buf[5];
|
||||
buf[0] = 0xb4; /* indicates a userid packet */
|
||||
buf[1] = uid->len >> 24; /* always use 4 length bytes */
|
||||
buf[2] = uid->len >> 16;
|
||||
buf[3] = uid->len >> 8;
|
||||
buf[4] = uid->len;
|
||||
md_write( md, buf, 5 );
|
||||
}
|
||||
md_write( md, uid->name, uid->len );
|
||||
}
|
||||
/* and make the signature packet */
|
||||
sig = m_alloc_clear( sizeof *sig );
|
||||
sig->version = sk->version;
|
||||
keyid_from_sk( sk, sig->keyid );
|
||||
sig->pubkey_algo = sk->pubkey_algo;
|
||||
sig->digest_algo = digest_algo;
|
||||
sig->timestamp = make_timestamp();
|
||||
sig->sig_class = sigclass;
|
||||
if( sig->version >= 4 )
|
||||
build_sig_subpkt_from_sig( sig );
|
||||
|
||||
if( sig->version >= 4 && mksubpkt )
|
||||
rc = (*mksubpkt)( sig, opaque );
|
||||
|
||||
if( !rc ) {
|
||||
if( sig->version >= 4 )
|
||||
md_putc( md, sig->version );
|
||||
md_putc( md, sig->sig_class );
|
||||
if( sig->version < 4 ) {
|
||||
u32 a = sig->timestamp;
|
||||
md_putc( md, (a >> 24) & 0xff );
|
||||
md_putc( md, (a >> 16) & 0xff );
|
||||
md_putc( md, (a >> 8) & 0xff );
|
||||
md_putc( md, a & 0xff );
|
||||
}
|
||||
else {
|
||||
byte buf[6];
|
||||
size_t n;
|
||||
|
||||
md_putc( md, sig->pubkey_algo );
|
||||
md_putc( md, sig->digest_algo );
|
||||
if( sig->hashed_data ) {
|
||||
n = (sig->hashed_data[0] << 8) | sig->hashed_data[1];
|
||||
md_write( md, sig->hashed_data, n+2 );
|
||||
n += 6;
|
||||
}
|
||||
else
|
||||
n = 6;
|
||||
/* add some magic */
|
||||
buf[0] = sig->version;
|
||||
buf[1] = 0xff;
|
||||
buf[2] = n >> 24; /* hmmm, n is only 16 bit, so this is always 0 */
|
||||
buf[3] = n >> 16;
|
||||
buf[4] = n >> 8;
|
||||
buf[5] = n;
|
||||
md_write( md, buf, 6 );
|
||||
|
||||
}
|
||||
md_final(md);
|
||||
|
||||
rc = complete_sig( sig, sk, md );
|
||||
}
|
||||
|
||||
md_close( md );
|
||||
if( rc )
|
||||
free_seckey_enc( sig );
|
||||
else
|
||||
*ret_sig = sig;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
522
g10/tdbio.c
522
g10/tdbio.c
@ -45,46 +45,8 @@ static char *db_name;
|
||||
static int db_fd = -1;
|
||||
|
||||
|
||||
|
||||
static void create_db( const char *fname );
|
||||
static void open_db(void);
|
||||
|
||||
/**************************************************
|
||||
************** read and write helpers ************
|
||||
**************************************************/
|
||||
|
||||
static void
|
||||
fwrite_8(FILE *fp, byte a)
|
||||
{
|
||||
if( putc( a & 0xff, fp ) == EOF )
|
||||
log_fatal("error writing byte to trustdb: %s\n", strerror(errno) );
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fwrite_32( FILE*fp, ulong a)
|
||||
{
|
||||
putc( (a>>24) & 0xff, fp );
|
||||
putc( (a>>16) & 0xff, fp );
|
||||
putc( (a>> 8) & 0xff, fp );
|
||||
if( putc( a & 0xff, fp ) == EOF )
|
||||
log_fatal("error writing ulong to trustdb: %s\n", strerror(errno) );
|
||||
}
|
||||
|
||||
static void
|
||||
fwrite_zeros( FILE *fp, size_t n)
|
||||
{
|
||||
while( n-- )
|
||||
if( putc( 0, fp ) == EOF )
|
||||
log_fatal("error writing zeros to trustdb: %s\n", strerror(errno) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************************
|
||||
************** read and write stuff **************
|
||||
**************************************************/
|
||||
|
||||
int
|
||||
tdbio_set_dbname( const char *new_dbname, int create )
|
||||
@ -101,7 +63,11 @@ tdbio_set_dbname( const char *new_dbname, int create )
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
if( create ) {
|
||||
FILE *fp;
|
||||
TRUSTREC rec;
|
||||
int rc;
|
||||
char *p = strrchr( fname, '/' );
|
||||
|
||||
assert(p);
|
||||
*p = 0;
|
||||
if( access( fname, F_OK ) ) {
|
||||
@ -119,7 +85,30 @@ tdbio_set_dbname( const char *new_dbname, int create )
|
||||
log_fatal_f(fname, _("directory does not exist!\n") );
|
||||
}
|
||||
*p = '/';
|
||||
create_db( fname );
|
||||
|
||||
fp =fopen( fname, "w" );
|
||||
if( !fp )
|
||||
log_fatal_f( fname, _("can't create: %s\n"), strerror(errno) );
|
||||
fclose(fp);
|
||||
m_free(db_name);
|
||||
db_name = fname;
|
||||
db_fd = open( db_name, O_RDWR );
|
||||
if( db_fd == -1 )
|
||||
log_fatal_f( db_name, _("can't open: %s\n"), strerror(errno) );
|
||||
|
||||
memset( &rec, 0, sizeof rec );
|
||||
rec.r.ver.version = 2;
|
||||
rec.r.ver.created = make_timestamp();
|
||||
rec.rectype = RECTYPE_VER;
|
||||
rec.recnum = 0;
|
||||
rc = tdbio_write_record( &rec );
|
||||
if( rc )
|
||||
log_fatal_f( fname, _("failed to create version record: %s"),
|
||||
g10_errstr(rc));
|
||||
/* and read again to check that we are okay */
|
||||
if( tdbio_read_record( 0, &rec, RECTYPE_VER ) )
|
||||
log_fatal_f( db_name, "invalid trust-db created\n" );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
m_free(db_name);
|
||||
@ -136,37 +125,6 @@ tdbio_get_dbname()
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
* Create a new trustdb
|
||||
*/
|
||||
static void
|
||||
create_db( const char *fname )
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp =fopen( fname, "w" );
|
||||
if( !fp )
|
||||
log_fatal_f( fname, _("can't create %s: %s\n"), strerror(errno) );
|
||||
fwrite_8( fp, 1 ); /* record type */
|
||||
fwrite_8( fp, 'g' );
|
||||
fwrite_8( fp, 'p' );
|
||||
fwrite_8( fp, 'g' );
|
||||
fwrite_8( fp, 2 ); /* version */
|
||||
fwrite_zeros( fp, 3 ); /* reserved */
|
||||
fwrite_32( fp, 0 ); /* not locked */
|
||||
fwrite_32( fp, make_timestamp() ); /* created */
|
||||
fwrite_32( fp, 0 ); /* not yet modified */
|
||||
fwrite_32( fp, 0 ); /* not yet validated*/
|
||||
fwrite_32( fp, 0 ); /* reserved */
|
||||
fwrite_8( fp, 3 ); /* marginals needed */
|
||||
fwrite_8( fp, 1 ); /* completes needed */
|
||||
fwrite_8( fp, 4 ); /* max_cet_depth */
|
||||
fwrite_zeros( fp, 9 ); /* filler */
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
open_db()
|
||||
{
|
||||
@ -182,10 +140,221 @@ open_db()
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Return the record number of the keyhash tbl or create a new one.
|
||||
*/
|
||||
static ulong
|
||||
get_keyhashrec()
|
||||
{
|
||||
static ulong keyhashtbl; /* record number of the key hashtable */
|
||||
TRUSTREC vr;
|
||||
int rc;
|
||||
|
||||
if( keyhashtbl )
|
||||
return keyhashtbl;
|
||||
|
||||
rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
|
||||
if( rc )
|
||||
log_fatal_f( db_name, _("error reading version record: %s\n"),
|
||||
g10_errstr(rc) );
|
||||
if( vr.r.ver.keyhashtbl )
|
||||
keyhashtbl = vr.r.ver.keyhashtbl;
|
||||
else {
|
||||
TRUSTREC rec;
|
||||
off_t offset;
|
||||
ulong recnum;
|
||||
int i, n;
|
||||
|
||||
offset = lseek( db_fd, 0, SEEK_END );
|
||||
if( offset == -1 )
|
||||
log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) );
|
||||
recnum = offset / TRUST_RECORD_LEN;
|
||||
assert(recnum); /* this is will never be the first record */
|
||||
|
||||
keyhashtbl = recnum;
|
||||
/* Now write the records */
|
||||
n = (256+ITEMS_PER_HTBL_RECORD-1) / ITEMS_PER_HTBL_RECORD;
|
||||
for(i=0; i < n; i++, recnum++ ) {
|
||||
memset( &rec, 0, sizeof rec );
|
||||
rec.rectype = RECTYPE_HTBL; /* free record */
|
||||
rec.recnum = recnum;
|
||||
rc = tdbio_write_record( &rec );
|
||||
if( rc )
|
||||
log_fatal_f(db_name,_("failed to create hashtable: %s\n"),
|
||||
g10_errstr(rc));
|
||||
}
|
||||
/* update the version record */
|
||||
vr.r.ver.keyhashtbl = keyhashtbl;
|
||||
rc = tdbio_write_record( &vr );
|
||||
if( rc )
|
||||
log_fatal_f( db_name, _("error updating version record: %s\n"),
|
||||
g10_errstr(rc));
|
||||
}
|
||||
return keyhashtbl;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
* Update the key hashtbl or create the table if it does not exist
|
||||
*/
|
||||
static int
|
||||
update_keyhashtbl( TRUSTREC *kr )
|
||||
{
|
||||
TRUSTREC lastrec, rec;
|
||||
ulong hashrec, item;
|
||||
int msb;
|
||||
int level=0;
|
||||
int rc, i;
|
||||
|
||||
hashrec = get_keyhashrec();
|
||||
next_level:
|
||||
msb = kr->r.key.fingerprint[level];
|
||||
hashrec += msb / ITEMS_PER_HTBL_RECORD;
|
||||
rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL );
|
||||
if( rc ) {
|
||||
log_error( db_name, "update_keyhashtbl read failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
|
||||
if( !item ) { /* insert new one */
|
||||
rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = kr->recnum;
|
||||
rc = tdbio_write_record( &rec );
|
||||
if( rc ) {
|
||||
log_error( db_name, "update_keyhashtbl write htbl failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
else if( item != kr->recnum ) { /* must do an update */
|
||||
lastrec = rec;
|
||||
rc = tdbio_read_record( item, &rec, 0 );
|
||||
if( rc ) {
|
||||
log_error( db_name, "update_keyhashtbl read item failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
if( rec.rectype == RECTYPE_HTBL ) {
|
||||
hashrec = item;
|
||||
level++;
|
||||
if( level >= kr->r.key.fingerprint_len ) {
|
||||
log_error( db_name, "keyhashtbl has invalid indirections\n");
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
goto next_level;
|
||||
}
|
||||
else if( rec.rectype == RECTYPE_HLST ) { /* extend list */
|
||||
/* see whether the key is already in this list */
|
||||
for(;;) {
|
||||
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
|
||||
if( rec.r.hlst.rnum[i] == kr->recnum ) {
|
||||
log_debug("HTBL: no update needed for keyrec %lu\n",
|
||||
kr->recnum );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if( rec.r.hlst.next ) {
|
||||
rc = tdbio_read_record( rec.r.hlst.next,
|
||||
&rec, RECTYPE_HLST);
|
||||
if( rc ) {
|
||||
log_error( db_name,
|
||||
"scan keyhashtbl read hlst failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
else
|
||||
break; /* not there */
|
||||
}
|
||||
/* find the next free entry and put it in */
|
||||
for(;;) {
|
||||
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
|
||||
if( !rec.r.hlst.rnum[i] ) {
|
||||
rec.r.hlst.rnum[i] = kr->recnum;
|
||||
rc = tdbio_write_record( &rec );
|
||||
if( rc )
|
||||
log_error( db_name,
|
||||
"update_keyhashtbl write hlst failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc; /* ready */
|
||||
}
|
||||
}
|
||||
if( rec.r.hlst.next ) {
|
||||
rc = tdbio_read_record( rec.r.hlst.next,
|
||||
&rec, RECTYPE_HLST );
|
||||
if( rc ) {
|
||||
log_error( db_name,
|
||||
"update_keyhashtbl read hlst failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
else { /* add a new list record */
|
||||
rec.r.hlst.next = item = tdbio_new_recnum();
|
||||
rc = tdbio_write_record( &rec );
|
||||
if( rc ) {
|
||||
log_error( db_name,
|
||||
"update_keyhashtbl write hlst failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
memset( &rec, 0, sizeof rec );
|
||||
rec.rectype = RECTYPE_HLST;
|
||||
rec.recnum = item;
|
||||
rec.r.hlst.rnum[0] = kr->recnum;
|
||||
if( rc )
|
||||
log_error( db_name,
|
||||
"update_keyhashtbl write ext hlst failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc; /* ready */
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( rec.rectype == RECTYPE_KEY ) { /* insert a list record */
|
||||
if( rec.recnum == kr->recnum ) {
|
||||
log_debug("HTBL: no update needed for keyrec %lu\n",
|
||||
kr->recnum );
|
||||
return 0;
|
||||
}
|
||||
item = rec.recnum; /* save number of key record */
|
||||
memset( &rec, 0, sizeof rec );
|
||||
rec.rectype = RECTYPE_HLST;
|
||||
rec.recnum = tdbio_new_recnum();
|
||||
rec.r.hlst.rnum[0] = item; /* old keyrecord */
|
||||
rec.r.hlst.rnum[1] = kr->recnum; /* and new one */
|
||||
rc = tdbio_write_record( &rec );
|
||||
if( rc ) {
|
||||
log_error( db_name,
|
||||
"update_keyhashtbl write new hlst failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
/* update the hashtable record */
|
||||
lastrec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = rec.recnum;
|
||||
rc = tdbio_write_record( &lastrec );
|
||||
if( rc )
|
||||
log_error( db_name,
|
||||
"update_keyhashtbl update htbl failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc; /* ready */
|
||||
}
|
||||
else {
|
||||
log_error( db_name, "keyhashtbl %lu points to an invalid record\n",
|
||||
item);
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
tdbio_dump_record( TRUSTREC *rec, FILE *fp )
|
||||
{
|
||||
int i, any;
|
||||
int i;
|
||||
ulong rnum = rec->recnum;
|
||||
|
||||
fprintf(fp, "rec %5lu, ", rnum );
|
||||
@ -193,7 +362,8 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
|
||||
switch( rec->rectype ) {
|
||||
case 0: fprintf(fp, "free\n");
|
||||
break;
|
||||
case RECTYPE_VER: fprintf(fp, "version\n");
|
||||
case RECTYPE_VER: fprintf(fp, "version, keyhashtbl=%lu\n",
|
||||
rec->r.ver.keyhashtbl );
|
||||
break;
|
||||
case RECTYPE_DIR:
|
||||
fprintf(fp, "dir %lu, keys=%lu, uids=%lu, cach=%lu, ot=%02x",
|
||||
@ -213,11 +383,12 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
|
||||
putc('\n', fp);
|
||||
break;
|
||||
case RECTYPE_KEY:
|
||||
fprintf(fp, "key %lu, next=%lu, algo=%d, flen=%d",
|
||||
fprintf(fp, "key %lu, next=%lu, algo=%d, ",
|
||||
rec->r.key.lid,
|
||||
rec->r.key.next,
|
||||
rec->r.key.pubkey_algo,
|
||||
rec->r.key.fingerprint_len );
|
||||
rec->r.key.pubkey_algo );
|
||||
for(i=0; i < rec->r.key.fingerprint_len; i++ )
|
||||
fprintf(fp, "%02X", rec->r.key.fingerprint[i] );
|
||||
if( rec->r.key.keyflags & KEYF_REVOKED )
|
||||
fputs(", revoked", fp );
|
||||
putc('\n', fp);
|
||||
@ -239,29 +410,29 @@ tdbio_dump_record( TRUSTREC *rec, FILE *fp )
|
||||
rec->r.uid.next);
|
||||
break;
|
||||
case RECTYPE_SIG:
|
||||
fprintf(fp, "sig %lu, next=%lu\n",
|
||||
fprintf(fp, "sig %lu, next=%lu,",
|
||||
rec->r.sig.lid, rec->r.sig.next );
|
||||
for(i=any=0; i < SIGS_PER_RECORD; i++ ) {
|
||||
if( rec->r.sig.sig[i].lid ) {
|
||||
if( !any ) {
|
||||
putc('\t', fp);
|
||||
any++;
|
||||
}
|
||||
fprintf(fp, " %lu:%02x", rec->r.sig.sig[i].lid,
|
||||
for(i=0; i < SIGS_PER_RECORD; i++ ) {
|
||||
if( rec->r.sig.sig[i].lid )
|
||||
fprintf(fp, " %lu:%02x", rec->r.sig.sig[i].lid,
|
||||
rec->r.sig.sig[i].flag );
|
||||
}
|
||||
}
|
||||
if( any )
|
||||
putc('\n', fp);
|
||||
putc('\n', fp);
|
||||
break;
|
||||
case RECTYPE_CACH:
|
||||
fprintf(fp, "cach\n");
|
||||
break;
|
||||
case RECTYPE_HTBL:
|
||||
fprintf(fp, "htbl\n");
|
||||
fprintf(fp, "htbl,");
|
||||
for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ )
|
||||
fprintf(fp, " %lu", rec->r.htbl.item[i] );
|
||||
putc('\n', fp);
|
||||
break;
|
||||
case RECTYPE_HLST:
|
||||
fprintf(fp, "hlst\n");
|
||||
fprintf(fp, "hlst, next=%lu,", rec->r.hlst.next );
|
||||
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ )
|
||||
fprintf(fp, " %lu", rec->r.hlst.rnum[i] );
|
||||
putc('\n', fp);
|
||||
break;
|
||||
default:
|
||||
fprintf(fp, "unknown type %d\n", rec->rectype );
|
||||
@ -302,30 +473,29 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
|
||||
recnum, expected, rec->rectype );
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
p++;
|
||||
p++; /* skip reserved byte */
|
||||
switch( rec->rectype ) {
|
||||
case 0: /* unused record */
|
||||
case 0: /* unused (free) record */
|
||||
break;
|
||||
case RECTYPE_VER: /* version record */
|
||||
if( memcmp(buf+1, "gpg", 3 ) ) {
|
||||
log_error_f( db_name, _("not a trustdb file\n") );
|
||||
rc = G10ERR_TRUSTDB;
|
||||
}
|
||||
p += 2; /* skip magic */
|
||||
p += 2; /* skip "pgp" */
|
||||
rec->r.ver.version = *p++;
|
||||
rec->r.ver.locked = buftoulong(p); p += 4;
|
||||
p += 3; /* reserved bytes */
|
||||
p += 4; /* lock flags */
|
||||
rec->r.ver.created = buftoulong(p); p += 4;
|
||||
rec->r.ver.modified = buftoulong(p); p += 4;
|
||||
rec->r.ver.validated= buftoulong(p); p += 4;
|
||||
rec->r.ver.marginals_needed = *p++;
|
||||
rec->r.ver.completes_needed = *p++;
|
||||
rec->r.ver.max_cert_depth = *p++;
|
||||
rec->r.ver.keyhashtbl=buftoulong(p); p += 4;
|
||||
if( recnum ) {
|
||||
log_error_f( db_name, "version record with recnum %lu\n",
|
||||
(ulong)recnum );
|
||||
rc = G10ERR_TRUSTDB;
|
||||
}
|
||||
if( rec->r.ver.version != 2 ) {
|
||||
else if( rec->r.ver.version != 2 ) {
|
||||
log_error_f( db_name, "invalid file version %d\n",
|
||||
rec->r.ver.version );
|
||||
rc = G10ERR_TRUSTDB;
|
||||
@ -381,6 +551,17 @@ tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
|
||||
memcpy(rec->r.cache.blockhash, p, 20); p += 20;
|
||||
rec->r.cache.trustlevel = *p++;
|
||||
break;
|
||||
case RECTYPE_HTBL:
|
||||
for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) {
|
||||
rec->r.htbl.item[i] = buftoulong(p); p += 4;
|
||||
}
|
||||
break;
|
||||
case RECTYPE_HLST:
|
||||
rec->r.hlst.next = buftoulong(p); p += 4;
|
||||
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
|
||||
rec->r.hlst.rnum[i] = buftoulong(p); p += 4;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log_error_f( db_name, "invalid record type %d at recnum %lu\n",
|
||||
rec->rectype, (ulong)recnum );
|
||||
@ -412,8 +593,16 @@ tdbio_write_record( TRUSTREC *rec )
|
||||
switch( rec->rectype ) {
|
||||
case 0: /* unused record */
|
||||
break;
|
||||
case 1: /* version record */
|
||||
BUG();
|
||||
case RECTYPE_VER: /* version record */
|
||||
if( recnum )
|
||||
BUG();
|
||||
memcpy(p-1, "gpg", 3 ); p += 2;
|
||||
*p++ = rec->r.ver.version;
|
||||
p += 7; /* skip reserved bytes and lock flags */
|
||||
ulongtobuf(p, rec->r.ver.created); p += 4;
|
||||
ulongtobuf(p, rec->r.ver.modified); p += 4;
|
||||
ulongtobuf(p, rec->r.ver.validated); p += 4;
|
||||
ulongtobuf(p, rec->r.ver.keyhashtbl); p += 4;
|
||||
break;
|
||||
|
||||
case RECTYPE_DIR: /*directory record */
|
||||
@ -466,6 +655,19 @@ tdbio_write_record( TRUSTREC *rec )
|
||||
*p++ = rec->r.cache.trustlevel;
|
||||
break;
|
||||
|
||||
case RECTYPE_HTBL:
|
||||
for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) {
|
||||
ulongtobuf( p, rec->r.htbl.item[i]); p += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case RECTYPE_HLST:
|
||||
ulongtobuf( p, rec->r.hlst.next); p += 4;
|
||||
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
|
||||
ulongtobuf( p, rec->r.hlst.rnum[i]); p += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
@ -479,6 +681,8 @@ tdbio_write_record( TRUSTREC *rec )
|
||||
log_error(_("trustdb: write failed (n=%d): %s\n"), n, strerror(errno) );
|
||||
return G10ERR_WRITE_FILE;
|
||||
}
|
||||
else if( rec->rectype == RECTYPE_KEY )
|
||||
rc = update_keyhashtbl( rec );
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -528,9 +732,6 @@ tdbio_new_recnum()
|
||||
/****************
|
||||
* Search the trustdb for a key which matches PK and return the dir record
|
||||
* The local_id of PK is set to the correct value
|
||||
*
|
||||
* Note: To increase performance, we could use a index search here.
|
||||
* tdbio_write_record shoudl create this index automagically
|
||||
*/
|
||||
int
|
||||
tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec )
|
||||
@ -540,32 +741,111 @@ tdbio_search_dir_record( PKT_public_key *pk, TRUSTREC *rec )
|
||||
byte *fingerprint;
|
||||
size_t fingerlen;
|
||||
int rc;
|
||||
ulong hashrec, item;
|
||||
int msb;
|
||||
int level=0;
|
||||
|
||||
keyid_from_pk( pk, keyid );
|
||||
fingerprint = fingerprint_from_pk( pk, NULL, &fingerlen );
|
||||
assert( fingerlen == 20 || fingerlen == 16 );
|
||||
|
||||
for(recnum=1; !(rc=tdbio_read_record( recnum, rec, 0)); recnum++ ) {
|
||||
if( rec->rectype != RECTYPE_KEY )
|
||||
continue;
|
||||
if( rec->r.key.pubkey_algo == pk->pubkey_algo
|
||||
&& !memcmp(rec->r.key.fingerprint, fingerprint, fingerlen) ) {
|
||||
/* found: read the dir record for this key */
|
||||
recnum = rec->r.key.lid;
|
||||
rc = tdbio_read_record( recnum, rec, RECTYPE_DIR);
|
||||
if( rc )
|
||||
break;
|
||||
if( pk->local_id && pk->local_id != recnum )
|
||||
log_error_f(db_name,
|
||||
"found record, but LID from memory does "
|
||||
"not match recnum (%lu,%lu)\n",
|
||||
pk->local_id, recnum );
|
||||
pk->local_id = recnum;
|
||||
return 0;
|
||||
}
|
||||
/* locate the key using the hash table */
|
||||
hashrec = get_keyhashrec();
|
||||
next_level:
|
||||
msb = fingerprint[level];
|
||||
hashrec += msb / ITEMS_PER_HTBL_RECORD;
|
||||
rc = tdbio_read_record( hashrec, rec, RECTYPE_HTBL );
|
||||
if( rc ) {
|
||||
log_error( db_name, "scan keyhashtbl failed: %s\n", g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
if( rc != -1 )
|
||||
log_error_f( db_name, _("search_db failed: %s\n"), g10_errstr(rc) );
|
||||
|
||||
item = rec->r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
|
||||
if( !item )
|
||||
return -1; /* not found */
|
||||
|
||||
rc = tdbio_read_record( item, rec, 0 );
|
||||
if( rc ) {
|
||||
log_error( db_name, "keyhashtbl read failed: %s\n", g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
if( rec->rectype == RECTYPE_HTBL ) {
|
||||
hashrec = item;
|
||||
level++;
|
||||
if( level >= fingerlen ) {
|
||||
log_error( db_name, "keyhashtbl has invalid indirections\n");
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
goto next_level;
|
||||
}
|
||||
else if( rec->rectype == RECTYPE_HLST ) {
|
||||
for(;;) {
|
||||
int i;
|
||||
|
||||
for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
|
||||
if( rec->r.hlst.rnum[i] ) {
|
||||
TRUSTREC tmp;
|
||||
|
||||
rc = tdbio_read_record( rec->r.hlst.rnum[i],
|
||||
&tmp, RECTYPE_KEY );
|
||||
if( rc ) {
|
||||
log_error( db_name,
|
||||
"scan keyhashtbl read key failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
if( tmp.r.key.pubkey_algo == pk->pubkey_algo
|
||||
&& tmp.r.key.fingerprint_len == fingerlen
|
||||
&& !memcmp(tmp.r.key.fingerprint,
|
||||
fingerprint, fingerlen) ) {
|
||||
*rec = tmp;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( rec->r.hlst.next ) {
|
||||
rc = tdbio_read_record( rec->r.hlst.next, rec, RECTYPE_HLST );
|
||||
if( rc ) {
|
||||
log_error( db_name,
|
||||
"scan keyhashtbl read hlst failed: %s\n",
|
||||
g10_errstr(rc) );
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
else
|
||||
return -1; /* not found */
|
||||
}
|
||||
found:
|
||||
;
|
||||
}
|
||||
else if( rec->rectype == RECTYPE_KEY ) {
|
||||
/* must check that it is the requested key */
|
||||
if( rec->r.key.pubkey_algo != pk->pubkey_algo
|
||||
|| rec->r.key.fingerprint_len != fingerlen
|
||||
|| memcmp(rec->r.key.fingerprint, fingerprint, fingerlen) )
|
||||
return -1; /* no: not found */
|
||||
}
|
||||
else {
|
||||
log_error( db_name, "keyhashtbl %lu points to an invalid record\n",
|
||||
item);
|
||||
return G10ERR_TRUSTDB;
|
||||
}
|
||||
|
||||
recnum = rec->r.key.lid;
|
||||
|
||||
if( pk->local_id && pk->local_id != recnum )
|
||||
log_error_f(db_name,
|
||||
"found record, but LID from memory does "
|
||||
"not match recnum (%lu,%lu)\n",
|
||||
pk->local_id, recnum );
|
||||
pk->local_id = recnum;
|
||||
|
||||
/* Now read the dir record */
|
||||
rc = tdbio_read_record( recnum, rec, RECTYPE_DIR);
|
||||
if( rc )
|
||||
log_error_f(db_name, "can't read dirrec %lu: %s\n",
|
||||
recnum, g10_errstr(rc) );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
14
g10/tdbio.h
14
g10/tdbio.h
@ -60,15 +60,12 @@ struct trust_record {
|
||||
int mark;
|
||||
ulong recnum;
|
||||
union {
|
||||
struct { /* version record: */
|
||||
byte version; /* should be 1 */
|
||||
ulong locked; /* pid of process which holds a lock */
|
||||
struct { /* version record: */
|
||||
byte version; /* should be 2 */
|
||||
ulong created; /* timestamp of trustdb creation */
|
||||
ulong modified; /* timestamp of last modification */
|
||||
ulong validated; /* timestamp of last validation */
|
||||
byte marginals_needed;
|
||||
byte completes_needed;
|
||||
byte max_cert_depth;
|
||||
ulong keyhashtbl;
|
||||
} ver;
|
||||
struct { /* directory record */
|
||||
ulong lid;
|
||||
@ -117,10 +114,7 @@ struct trust_record {
|
||||
} htbl;
|
||||
struct {
|
||||
ulong next;
|
||||
struct {
|
||||
byte hash;
|
||||
ulong rnum;
|
||||
} item[ITEMS_PER_HLST_RECORD];
|
||||
ulong rnum[ITEMS_PER_HLST_RECORD]; /* of a key record */
|
||||
} hlst;
|
||||
} r;
|
||||
};
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@ -102,6 +103,9 @@ static ulong last_trust_web_key;
|
||||
static TRUST_SEG_LIST last_trust_web_tslist;
|
||||
|
||||
|
||||
#define HEXTOBIN(a) ( (a) >= '0' && (a) <= '9' ? ((a)-'0') : \
|
||||
(a) >= 'A' && (a) <= 'F' ? ((a)-'A'+10) : ((a)-'a'+10))
|
||||
|
||||
/**********************************************
|
||||
************* list helpers *******************
|
||||
**********************************************/
|
||||
@ -945,6 +949,7 @@ update_sigs( TRUSTREC *dir )
|
||||
}
|
||||
else {
|
||||
/* fixme: handle other sig classes here */
|
||||
/* FIXME: Revocations!!! */
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1243,7 +1248,16 @@ list_trustdb( const char *username )
|
||||
{
|
||||
TRUSTREC rec;
|
||||
|
||||
if( username ) {
|
||||
if( username && *username == '#' ) {
|
||||
int rc;
|
||||
ulong lid = atoi(username+1);
|
||||
|
||||
if( (rc = list_records( lid)) )
|
||||
log_error("user '%s' read problem: %s\n", username, g10_errstr(rc));
|
||||
else if( (rc = list_sigs( lid )) )
|
||||
log_error("user '%s' list problem: %s\n", username, g10_errstr(rc));
|
||||
}
|
||||
else if( username ) {
|
||||
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
|
||||
int rc;
|
||||
|
||||
@ -1274,10 +1288,10 @@ list_trustdb( const char *username )
|
||||
}
|
||||
|
||||
/****************
|
||||
* make a list of all defined owner trust value.
|
||||
* Print a list of all defined owner trust value.
|
||||
*/
|
||||
void
|
||||
list_ownertrust()
|
||||
export_ownertrust()
|
||||
{
|
||||
TRUSTREC rec;
|
||||
TRUSTREC rec2;
|
||||
@ -1307,6 +1321,67 @@ list_ownertrust()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
import_ownertrust( const char *fname )
|
||||
{
|
||||
FILE *fp;
|
||||
int is_stdin=0;
|
||||
char line[256];
|
||||
char *p;
|
||||
size_t n, fprlen;
|
||||
unsigned otrust;
|
||||
|
||||
if( !fname || (*fname == '-' && !fname[1]) ) {
|
||||
fp = stdin;
|
||||
fname = "[stdin]";
|
||||
is_stdin = 1;
|
||||
}
|
||||
else if( !(fp = fopen( fname, "r" )) ) {
|
||||
log_error_f(fname, _("can't open file: %s\n"), strerror(errno) );
|
||||
return;
|
||||
}
|
||||
|
||||
while( fgets( line, DIM(line)-1, fp ) ) {
|
||||
if( !*line || *line == '#' )
|
||||
continue;
|
||||
n = strlen(line);
|
||||
if( line[n-1] != '\n' ) {
|
||||
log_error_f(fname, "line to long\n" );
|
||||
break; /* can't continue */
|
||||
}
|
||||
for(p = line; *p && *p != ':' ; p++ )
|
||||
if( !isxdigit(*p) )
|
||||
break;
|
||||
if( *p != ':' ) {
|
||||
log_error_f(fname, "error: missing colon\n" );
|
||||
continue;
|
||||
}
|
||||
fprlen = p - line;
|
||||
if( fprlen != 32 && fprlen != 40 ) {
|
||||
log_error_f(fname, "error: invalid fingerprint\n" );
|
||||
continue;
|
||||
}
|
||||
if( sscanf(p, ":%u:", &otrust ) != 1 ) {
|
||||
log_error_f(fname, "error: no otrust value\n" );
|
||||
continue;
|
||||
}
|
||||
if( !otrust )
|
||||
continue; /* no otrust defined - no need to update or insert */
|
||||
/* convert the ascii fingerprint to binary */
|
||||
for(p=line, fprlen=0; *p != ':'; p += 2 )
|
||||
line[fprlen++] = HEXTOBIN(p[0]) * 16 + HEXTOBIN(p[1]);
|
||||
line[fprlen] = 0;
|
||||
|
||||
log_hexdump("found: ", line, fprlen );
|
||||
}
|
||||
if( ferror(fp) )
|
||||
log_error_f(fname, _("read error: %s\n"), strerror(errno) );
|
||||
if( !is_stdin )
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
list_trust_path( int max_depth, const char *username )
|
||||
{
|
||||
@ -1405,7 +1480,17 @@ check_trustdb( const char *username )
|
||||
TRUSTREC rec;
|
||||
int rc;
|
||||
|
||||
if( username ) {
|
||||
if( username && *username == '#' ) {
|
||||
int rc;
|
||||
ulong lid = atoi(username+1);
|
||||
|
||||
if( (rc = update_sigs_by_lid( lid )) )
|
||||
log_error("lid %lu: check failed: %s\n",
|
||||
lid, g10_errstr(rc));
|
||||
else
|
||||
log_info("lid %lu: checked: %s\n", lid, g10_errstr(rc));
|
||||
}
|
||||
else if( username ) {
|
||||
PKT_public_key *pk = m_alloc_clear( sizeof *pk );
|
||||
|
||||
if( (rc = get_pubkey_byname( pk, username )) )
|
||||
@ -1724,7 +1809,7 @@ insert_trust_record( PKT_public_key *orig_pk )
|
||||
BUG(); /* more than one primary key */
|
||||
keyid_from_pk( pk, keyid );
|
||||
}
|
||||
fingerprint = fingerprint_from_pk( orig_pk, NULL, &fingerlen );
|
||||
fingerprint = fingerprint_from_pk( pk, NULL, &fingerlen );
|
||||
rec = m_alloc_clear( sizeof *rec );
|
||||
rec->rectype = RECTYPE_KEY;
|
||||
rec->r.key.pubkey_algo = pk->pubkey_algo;
|
||||
|
@ -38,7 +38,8 @@
|
||||
/*-- trustdb.c --*/
|
||||
void list_trustdb(const char *username);
|
||||
void list_trust_path( int max_depth, const char *username );
|
||||
void list_ownertrust(void);
|
||||
void export_ownertrust(void);
|
||||
void import_ownertrust(const char *fname);
|
||||
void check_trustdb( const char *username );
|
||||
int init_trustdb( int level, const char *dbname );
|
||||
int check_trust( PKT_public_key *pk, unsigned *r_trustlevel );
|
||||
|
@ -35,6 +35,7 @@
|
||||
#define CIPHER_ALGO_DES_SK 6
|
||||
#define CIPHER_ALGO_BLOWFISH160 42 /* blowfish 160 bit key (not in OpenPGP)*/
|
||||
#define CIPHER_ALGO_SKIPJACK 101 /* experimental: skipjack */
|
||||
#define CIPHER_ALGO_TWOFISH 102 /* experimental: twofish 128 bit */
|
||||
#define CIPHER_ALGO_DUMMY 110 /* no encryption at all */
|
||||
|
||||
#define PUBKEY_ALGO_RSA 1
|
||||
@ -130,6 +131,7 @@ int string_to_cipher_algo( const char *string );
|
||||
const char * cipher_algo_to_string( int algo );
|
||||
int check_cipher_algo( int algo );
|
||||
unsigned cipher_get_keylen( int algo );
|
||||
unsigned cipher_get_blocksize( int algo );
|
||||
CIPHER_HANDLE cipher_open( int algo, int mode, int secure );
|
||||
void cipher_close( CIPHER_HANDLE c );
|
||||
void cipher_setkey( CIPHER_HANDLE c, byte *key, unsigned keylen );
|
||||
|
@ -25,6 +25,7 @@ void tty_print_string( byte *p, size_t n );
|
||||
char *tty_get( const char *prompt );
|
||||
char *tty_get_hidden( const char *prompt );
|
||||
void tty_kill_prompt(void);
|
||||
int tty_get_answer_is_yes( const char *prompt );
|
||||
|
||||
|
||||
#endif /*G10_TTYIO_H*/
|
||||
|
@ -49,7 +49,7 @@ g10m_release( MPI a )
|
||||
void
|
||||
g10m_resize( MPI a, unsigned nbits )
|
||||
{
|
||||
return mpi_resize( a, (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB );
|
||||
mpi_resize( a, (nbits+BITS_PER_MPI_LIMB-1) / BITS_PER_MPI_LIMB );
|
||||
}
|
||||
|
||||
MPI g10m_copy( MPI a ) { return mpi_copy( a ); }
|
||||
|
@ -120,6 +120,7 @@ mpi_invm( MPI x, MPI a, MPI n )
|
||||
mpi_rshift(t2, t2, 1);
|
||||
mpi_rshift(t3, t3, 1);
|
||||
Y4:
|
||||
;
|
||||
} while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */
|
||||
|
||||
if( !t3->sign ) {
|
||||
@ -216,6 +217,7 @@ mpi_invm( MPI x, MPI a, MPI n )
|
||||
mpi_rshift(t3, t3, 1);
|
||||
}
|
||||
Y4:
|
||||
;
|
||||
} while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */
|
||||
|
||||
if( !t3->sign ) {
|
||||
|
15
po/de.po
15
po/de.po
@ -400,11 +400,6 @@ msgstr "--clearsign [Dateiname]"
|
||||
msgid "--decrypt [filename]"
|
||||
msgstr "--decrypt [Dateiname]"
|
||||
|
||||
#. sign the key given as argument
|
||||
#: g10/g10.c:802
|
||||
msgid "--sign-key username"
|
||||
msgstr "--sign-key Benutzername"
|
||||
|
||||
#: g10/g10.c:810
|
||||
msgid "--edit-key username"
|
||||
msgstr "--edit-key Benutzername"
|
||||
@ -417,12 +412,6 @@ msgstr "--delete-secret-key Benutzername"
|
||||
msgid "--delete-key username"
|
||||
msgstr "--delete-key Benutzername"
|
||||
|
||||
#. Change the passphrase
|
||||
#. no arg: use default, 1 arg use this one
|
||||
#: g10/g10.c:829
|
||||
msgid "--change-passphrase [username]"
|
||||
msgstr "--change-passphrase [Benutzername]"
|
||||
|
||||
#. prepare iobufs
|
||||
#: g10/encode.c:200 g10/g10.c:853 g10/keylist.c:79
|
||||
msgid "can't open %s: %s\n"
|
||||
@ -810,12 +799,12 @@ msgstr "\"passphrase\" nicht richtig wiederholt; noch einmal.\n"
|
||||
msgid ""
|
||||
"You don't want a passphrase - this is probably a *bad* idea!\n"
|
||||
"I will do it anyway. You can change your passphrase at any time,\n"
|
||||
"using this program with the option \"--change-passphrase\".\n"
|
||||
"using this program with the option \"--edit-key\".\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
"Sie m\366chten keine \"passphrase\" - Dies ist eine *schlechte* Idee!\n"
|
||||
"Es ist trotzdem m\366glich. Sie k\366nnen Ihre \"phassphrase\" jederzeit\n"
|
||||
"\344ndern, indem sie dieses Programm mit dem Kommando \"--change-passphrase\"\n"
|
||||
"\344ndern, indem sie dieses Programm mit dem Kommando \"--edit-key\"\n"
|
||||
"aufrufen.\n"
|
||||
"\n"
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
Wed Jul 29 14:53:34 1998 Werner Koch (wk@(none))
|
||||
|
||||
* ttyio.c (tty_get_answer_is_yes): New.
|
||||
|
||||
Tue Jul 21 10:35:48 1998 Werner Koch (wk@(none))
|
||||
|
||||
* argparse.c: New option flag to distinguish options and commands.
|
||||
|
@ -91,3 +91,4 @@ answer_is_yes( const char *s )
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -204,7 +204,7 @@ secmem_malloc( size_t size )
|
||||
}
|
||||
/* allocate a new block */
|
||||
if( (poollen + size <= poolsize) ) {
|
||||
mb = pool + poollen;
|
||||
mb = (void*)((char*)pool + poollen);
|
||||
poollen += size;
|
||||
mb->size = size;
|
||||
}
|
||||
@ -240,7 +240,7 @@ secmem_realloc( void *p, size_t newsize )
|
||||
return p; /* it is easier not to shrink the memory */
|
||||
a = secmem_malloc( newsize );
|
||||
memcpy(a, p, size);
|
||||
memset(a+size, 0, newsize-size);
|
||||
memset((char*)a+size, 0, newsize-size);
|
||||
secmem_free(p);
|
||||
return a;
|
||||
}
|
||||
@ -271,7 +271,7 @@ secmem_free( void *a )
|
||||
int
|
||||
m_is_secure( const void *p )
|
||||
{
|
||||
return p >= pool && p < (pool+poolsize);
|
||||
return p >= pool && p < ((char*)pool+poolsize);
|
||||
}
|
||||
|
||||
void
|
||||
|
12
util/ttyio.c
12
util/ttyio.c
@ -328,3 +328,15 @@ tty_kill_prompt()
|
||||
last_prompt_len = 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
tty_get_answer_is_yes( const char *prompt )
|
||||
{
|
||||
int yes;
|
||||
char *p = tty_get( prompt );
|
||||
tty_kill_prompt();
|
||||
yes = answer_is_yes(p);
|
||||
m_free(p);
|
||||
return yes;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user