1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-09 12:54:23 +01:00

MDC feature support and other stuff

This commit is contained in:
Werner Koch 2001-08-30 16:39:23 +00:00
parent 64d586ef17
commit bab40b52cd
24 changed files with 404 additions and 331 deletions

6
NEWS
View File

@ -24,7 +24,11 @@
* Merged Stefan's patches for RISC OS in. See comments in * Merged Stefan's patches for RISC OS in. See comments in
scripts/build-riscos. scripts/build-riscos.
* It is now possible to sign an convenional encrypt a message (-cs). * It is now possible to sign and convenional encrypt a message (-cs).
* The MDC feature flag is supported and can be set by using
the "updpref" edit command.
Noteworthy changes in version 1.0.6 (2001-05-29) Noteworthy changes in version 1.0.6 (2001-05-29)
------------------------------------------------ ------------------------------------------------

16
TODO
View File

@ -1,4 +1,5 @@
* need a BAD_PASSPHRASE status for -c
* add listing of notation data * add listing of notation data
@ -9,11 +10,6 @@
* Show more info does not work from edit->trust * Show more info does not work from edit->trust
* keyedit_menu: We first look for a secret key and then for a public
key. This is bad we must match the keys. Better check all places
were we match keys. build_sig_packet: implement update for
sig-creation.
* set default charset from nl_langinfo. * set default charset from nl_langinfo.
* check all mpi_read() for error returns. * check all mpi_read() for error returns.
@ -79,10 +75,18 @@
preferences is okay and make AES the default. preferences is okay and make AES the default.
* Concatenated encryption messages don't work corectly - only the * Concatenated encryption messages don't work corectly - only the
first one is processes. first one is processed.
* Add status message for reasons why a key was not selected. * Add status message for reasons why a key was not selected.
* Add option to put the list of recipients (from the encryption
layer) into the signatures notation data.
* v3 RSA keys do work but the user IDs are shown as [?] which
cheking the signatures. Reported by Dave Dykstra. Print
"[uncertain]" + user ID
Scheduled for 1.1 Scheduled for 1.1
----------------- -----------------
* export by user-IDs does only export the first matching name which leads * export by user-IDs does only export the first matching name which leads

View File

@ -18,3 +18,8 @@ secret key 9D266E0F expired at
: expired at : expired at
gpg: Note: This key has expired! gpg: Note: This key has expired!
gpg: Fingerprint: 0826 1CB7 C976 5344 E207 4184 3C6B BBE6 9D26 6E0F gpg: Fingerprint: 0826 1CB7 C976 5344 E207 4184 3C6B BBE6 9D26 6E0F
gpg: 3DES encrypted data
gpg: CAST5 encrypted data
gpg: BLOWFISH encrypted data
gpg: TWOFISH encrypted data
gpg: RIJNDAEL encrypted data

View File

@ -1,3 +1,8 @@
2001-08-29 Werner Koch <wk@gnupg.org>
* faq.raw: Described how to delete a secret key w/o a public key
and changed the entry on updating the preferences.
2001-08-08 Werner Koch <wk@gnupg.org> 2001-08-08 Werner Koch <wk@gnupg.org>
* gpg.sgml: Documented --print-mds and marked the --print-md * as * gpg.sgml: Documented --print-mds and marked the --print-md * as

View File

@ -227,7 +227,7 @@ more arguments in future versions.
Mark the start and end of the actual decryption process. These Mark the start and end of the actual decryption process. These
are also emitted when in --list-only mode. are also emitted when in --list-only mode.
BEGIN_ENCRYPTION BEGIN_ENCRYPTION <mdc_method> <sym_algo>
END_ENCRYPTION END_ENCRYPTION
Mark the start and end of the actual encryption process. Mark the start and end of the actual encryption process.

88
doc/FAQ
View File

@ -45,21 +45,22 @@ you could search in the mailing list archive.
4.4) What is the difference between options and commands? 4.4) What is the difference between options and commands?
4.5) I can't delete an user id because it is already deleted on my public 4.5) I can't delete an user id because it is already deleted on my public
keyring? keyring?
4.6) What are trust, validity and ownertrust? 4.6) I can't delete the secret key because my public key disappeared?
4.7) How do I sign a patch file? 4.7) What are trust, validity and ownertrust?
4.8) Where is the "encrypt-to-self" option? 4.8) How do I sign a patch file?
4.9) How can I get rid of the Version and Comment headers in armored 4.9) Where is the "encrypt-to-self" option?
4.10) How can I get rid of the Version and Comment headers in armored
messages? messages?
4.10) What does the "You are using the xxxx character set." mean? 4.11) What does the "You are using the xxxx character set." mean?
4.11) How can a get list of key IDs used to encrypt a message? 4.12) How can a get list of key IDs used to encrypt a message?
4.12) I can't decrypt my symmetrical only (-c) encrypted message with 4.13) I can't decrypt my symmetrical only (-c) encrypted message with
a new version of GnuPG. a new version of GnuPG.
4.13) How can I used GnuPG in an automated environment? 4.14) How can I used GnuPG in an automated environment?
4.14) Which email-client can I use with GnuPG? 4.15) Which email-client can I use with GnuPG?
4.15) Can't we have a gpg library? 4.16) Can't we have a gpg library?
4.16) I have successfully generated a revocation certificate, but I don't 4.17) I have successfully generated a revocation certificate, but I don't
understand how to send it to the key servers. understand how to send it to the key servers.
4.17) How do I put my keyring in a different directory? 4.18) How do I put my keyring in a different directory?
5. COMPATIBILITY ISSUES 5. COMPATIBILITY ISSUES
5.1) How can I encrypt a message with GnuPG so that PGP is able to decrypt it? 5.1) How can I encrypt a message with GnuPG so that PGP is able to decrypt it?
@ -330,7 +331,18 @@ keyring?
ring. Now select this user id and delete it. Both user ids will be ring. Now select this user id and delete it. Both user ids will be
removed from the secret ring. removed from the secret ring.
4.6) What are trust, validity and ownertrust? 4.6) I can't delete the secret key because my public key disappeared?
To select a key a search is always done on the public keyring,
therefore it is not possible to select an secret key without
having the public key. Normally it shoud never happen that the
public key got lost but the secret key is still available. The
reality is different, so we GnuPG implements a special way to do
deal with it: Simply use the long keyid which you can figure out
by using the --with-colons options (it is the fifth field in the
lines beginning with "sec").
4.7) What are trust, validity and ownertrust?
"ownertrust" is used instead of "trust" to make clear that this is "ownertrust" is used instead of "trust" to make clear that this is
the value you have assigned to a key to express how much you trust the value you have assigned to a key to express how much you trust
@ -340,7 +352,7 @@ keyring?
who claims to be the owner of the key). For more see the chapter who claims to be the owner of the key). For more see the chapter
"The Web of Trust" in the Manual. "The Web of Trust" in the Manual.
4.7) How do I sign a patch file? 4.8) How do I sign a patch file?
Use "gpg --clearsign --not-dash-escaped ...". The problem with Use "gpg --clearsign --not-dash-escaped ...". The problem with
--clearsign is that all lines starting with a dash are quoted with --clearsign is that all lines starting with a dash are quoted with
@ -353,19 +365,19 @@ keyring?
mailer may not preserve these. If you want to mail a file you can mailer may not preserve these. If you want to mail a file you can
simply sign it using your MUA. simply sign it using your MUA.
4.8) Where is the "encrypt-to-self" option? 4.9) Where is the "encrypt-to-self" option?
Use "--encrypt-to your_keyid". You can use more than one of these Use "--encrypt-to your_keyid". You can use more than one of these
options. To temporary override the use of this additional keys, you options. To temporary override the use of this additional keys, you
can use the option "--no-encrypt-to". can use the option "--no-encrypt-to".
4.9) How can I get rid of the Version and Comment headers in armored 4.10) How can I get rid of the Version and Comment headers in armored
messages? messages?
Use "--no-version --comment ''". Note that the left over blank line Use "--no-version --comment ''". Note that the left over blank line
is required by the protocol. is required by the protocol.
4.10) What does the "You are using the xxxx character set." mean? 4.11) What does the "You are using the xxxx character set." mean?
This note is printed when UTF8 mapping has to be done. Make sure This note is printed when UTF8 mapping has to be done. Make sure
that the displayed charset is the one you have activated on your that the displayed charset is the one you have activated on your
@ -375,12 +387,12 @@ messages?
if not, restrict yourself to plain 7 bit ASCII and no mapping has to if not, restrict yourself to plain 7 bit ASCII and no mapping has to
be done. be done.
4.11) How can a get list of key IDs used to encrypt a message? 4.12) How can a get list of key IDs used to encrypt a message?
gpg --batch --decrypt --list-only --status-fd 1 2>/dev/null | \ gpg --batch --decrypt --list-only --status-fd 1 2>/dev/null | \
awk '/^\[GNUPG:\] ENC_TO / { print $3 }' awk '/^\[GNUPG:\] ENC_TO / { print $3 }'
4.12) I can't decrypt my symmetrical only (-c) encrypted message with 4.13) I can't decrypt my symmetrical only (-c) encrypted message with
a new version of GnuPG. a new version of GnuPG.
There used to be a bug in GnuPG < 1.0.1 which happens only if 3DES There used to be a bug in GnuPG < 1.0.1 which happens only if 3DES
@ -391,7 +403,7 @@ messages?
without this option. The option will be removed in 1.1, so better without this option. The option will be removed in 1.1, so better
re-encrypt your message now. re-encrypt your message now.
4.13) How can I used GnuPG in an automated environment? 4.14) How can I used GnuPG in an automated environment?
You should use the option --batch and don't use pass phrases as You should use the option --batch and don't use pass phrases as
there is usually no way to store it more secure than the secret there is usually no way to store it more secure than the secret
@ -415,7 +427,7 @@ messages?
turn can revoke all the subkeys installed on that machine and turn can revoke all the subkeys installed on that machine and
install new subkeys. install new subkeys.
4.14) Which email-client can I use with GnuPG? 4.15) Which email-client can I use with GnuPG?
Using GnuPG to encrypt email is one of the most popular Using GnuPG to encrypt email is one of the most popular
uses. Several mail clients or mail user-agents (MUA) support GnuPG uses. Several mail clients or mail user-agents (MUA) support GnuPG
@ -441,7 +453,7 @@ messages?
may be possible to use a wrapper. may be possible to use a wrapper.
4.15) Can't we have a gpg library? 4.16) Can't we have a gpg library?
This has been frequently requested. However, the current viewpoint This has been frequently requested. However, the current viewpoint
of the GnuPG maintainers is that this would lead to several security of the GnuPG maintainers is that this would lead to several security
@ -451,7 +463,7 @@ messages?
ftp://ftp.guug.de/pub/gcrypt/alpha/gpgme ftp://ftp.guug.de/pub/gcrypt/alpha/gpgme
4.16) I have successfully generated a revocation certificate, but I don't 4.17) I have successfully generated a revocation certificate, but I don't
understand how to send it to the key servers. understand how to send it to the key servers.
Most keyservers don't accept a 'bare' revocation certificate. You Most keyservers don't accept a 'bare' revocation certificate. You
@ -462,7 +474,7 @@ messages?
(or use a keyserver web interface for this). (or use a keyserver web interface for this).
4.17) How do I put my keyring in a different directory? 4.18) How do I put my keyring in a different directory?
GnuPG keeps several files in a special homedir directory. These GnuPG keeps several files in a special homedir directory. These
include the options file, pubring.gpg, secring.gpg, the trustdb, and include the options file, pubring.gpg, secring.gpg, the trustdb, and
@ -915,25 +927,15 @@ material?
7.8) How do I change the list of preferred algorithms? 7.8) How do I change the list of preferred algorithms?
Currently the default is hard-wired into the GnuPG source code. Use the edit menu and set the new list of preference using the
You'll have to change g10/keygen.c and recompile. The command "setpref"; the format of this command resembles the output
function you'll have to change is keygen_add_std_prefs. of the command "pref". The preference are not changes immediately
The code is pretty self-explanatory. The constants used to but the set preference will be used when a new user ID is
denote the algorithms are defined in include/cipher.h. created. If you want to update the preferences for existing user
IDs, select those user IDs (or select none to update all) and
After having done that, generate a new key pair (or a new encryption enter the command "updpref". Note that the timestamp of the
subkey) with the modified executable. This new key will have the self-signaures is increaded by one second when running this
modified preferences and can then be used with unmodified executables. command.
To modify the preferences of an existing key, use a modified
executable (see above) to change the expiry date and then save the
key. The use your original expiry date and save the key again. Now
you've got the prefs changed and can use the key again with your
unmodified executable.
Changing the list of preferences with an unmodified GnuPG
executable (possibly in the edit-key menu) is on the TODO list and
planned for future releases.
8. ACKNOWLEDGEMENTS 8. ACKNOWLEDGEMENTS

View File

@ -279,6 +279,17 @@ keyring?
ring. Now select this user id and delete it. Both user ids will be ring. Now select this user id and delete it. Both user ids will be
removed from the secret ring. removed from the secret ring.
<Q> I can't delete the secret key because my public key disappeared?
To select a key a search is always done on the public keyring,
therefore it is not possible to select an secret key without
having the public key. Normally it shoud never happen that the
public key got lost but the secret key is still available. The
reality is different, so we GnuPG implements a special way to do
deal with it: Simply use the long keyid which you can figure out
by using the --with-colons options (it is the fifth field in the
lines beginning with "sec").
<Q> What are trust, validity and ownertrust? <Q> What are trust, validity and ownertrust?
"ownertrust" is used instead of "trust" to make clear that this is "ownertrust" is used instead of "trust" to make clear that this is
@ -887,25 +898,15 @@ material?
<Q> How do I change the list of preferred algorithms? <Q> How do I change the list of preferred algorithms?
Currently the default is hard-wired into the GnuPG source code. Use the edit menu and set the new list of preference using the
You'll have to change [H pre]g10/keygen.c[H/pre] and recompile. The command "setpref"; the format of this command resembles the output
function you'll have to change is [H pre]keygen_add_std_prefs[H /pre]. of the command "pref". The preference are not changes immediately
The code is pretty self-explanatory. The constants used to but the set preference will be used when a new user ID is
denote the algorithms are defined in [H pre]include/cipher.h[H /pre]. created. If you want to update the preferences for existing user
IDs, select those user IDs (or select none to update all) and
After having done that, generate a new key pair (or a new encryption enter the command "updpref". Note that the timestamp of the
subkey) with the modified executable. This new key will have the self-signaures is increaded by one second when running this
modified preferences and can then be used with unmodified executables. command.
To modify the preferences of an existing key, use a modified
executable (see above) to change the expiry date and then save the
key. The use your original expiry date and save the key again. Now
you've got the prefs changed and can use the key again with your
unmodified executable.
Changing the list of preferences with an unmodified GnuPG
executable (possibly in the edit-key menu) is on the TODO list and
planned for future releases.
<S> ACKNOWLEDGEMENTS <S> ACKNOWLEDGEMENTS

View File

@ -1,3 +1,45 @@
2001-08-30 Werner Koch <wk@gnupg.org>
* packet.h (sigsubpkttype_t): Add SIGSUBPKT_FEATURES.
(PKT_public_key, PKT_user_id): Add a flag for it.
* parse-packet.c, build-packet.c: Add support for them.
* getkey.c (fixup_uidnode, merge_selfsigs): Set the MDC flags.
* keygen.c (add_feature_mdc): New.
(keygen_upd_std_prefs): Always set the MDC feature.
* keyedit.c (show_prefs): List the MDC flag
* pkclist.c (select_mdc_from_pklist): New.
* encode.c (encode_crypt, encrypt_filter): Test whether MDC
should be used.
* cipher.c (write_header): Set MDC use depending on the above test.
Print more status info.
* delkey.c (do_delete_key): Kludge to delete a secret key with no
public key available.
* ringedit.c (find_secret_keyblock_direct): New.
* getkey.c (seckey_available): Simplified.
* ringedit.c (cmp_seckey): Now compares the secret key against the
public key while ignoring all secret parts.
(keyring_search): Use a public key packet as arg. Allow to search
for subnkeys
(search): Likewise. Changed all callers.
(find_secret_keyblock_bypk): New.
(find_secret_keyblock_byname): First locate the pubkey and then
find the correponding secret key.
* parse-packet.c (parse): Renamed pkttype arg to onlykeypkts and
changed code accordingly. Changed all callers.
(search_packet): Removed pkttype arg.
* keyedit.c (keyedit_menu): First locate the public key and then
try to locate a secret key.
* ringedit.c (locate_keyblock_by_fpr): Removed.
(locate_keyblock_by_keyid): Removed.
(find_keyblock_bysk): Removed.
* sig-check.c (check_key_signature2): Print the keyid along with
the wrong sig class errors.
2001-08-24 Werner Koch <wk@gnupg.org> 2001-08-24 Werner Koch <wk@gnupg.org>
* sign.c (sign_file): Stripped the disabled comment packet code. * sign.c (sign_file): Stripped the disabled comment packet code.

View File

@ -747,6 +747,7 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type,
case SIGSUBPKT_PREF_SYM: case SIGSUBPKT_PREF_SYM:
case SIGSUBPKT_PREF_HASH: case SIGSUBPKT_PREF_HASH:
case SIGSUBPKT_PREF_COMPR: case SIGSUBPKT_PREF_COMPR:
case SIGSUBPKT_FEATURES:
delete_sig_subpkt (sig->hashed, type); delete_sig_subpkt (sig->hashed, type);
break; break;
default: default:
@ -783,6 +784,7 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type,
case SIGSUBPKT_REVOC_REASON: case SIGSUBPKT_REVOC_REASON:
case SIGSUBPKT_PRIMARY_UID: case SIGSUBPKT_PRIMARY_UID:
case SIGSUBPKT_KEY_FLAGS: case SIGSUBPKT_KEY_FLAGS:
case SIGSUBPKT_FEATURES:
hashed = 1; break; hashed = 1; break;
default: hashed = 0; break; default: hashed = 0; break;
} }

View File

@ -47,16 +47,27 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
byte temp[18]; byte temp[18];
unsigned blocksize; unsigned blocksize;
unsigned nprefix; unsigned nprefix;
int use_mdc = opt.force_mdc; int use_mdc;
blocksize = cipher_get_blocksize( cfx->dek->algo ); blocksize = cipher_get_blocksize( cfx->dek->algo );
if( blocksize < 8 || blocksize > 16 ) if( blocksize < 8 || blocksize > 16 )
log_fatal("unsupported blocksize %u\n", blocksize ); log_fatal("unsupported blocksize %u\n", blocksize );
use_mdc = cfx->dek->use_mdc;
if( blocksize != 8 ) if( blocksize != 8 )
use_mdc = 1; /* enable it for all modern ciphers */ use_mdc = 1; /* Hack: enable it for all modern ciphers */
/* Note: We should remove this hack as soon as a reasonable number of keys
are carrying the MDC flag. But always keep the hack for conventional
encryption */
if (opt.force_mdc)
use_mdc = 1;
if( opt.rfc2440 || opt.rfc1991 ) if( opt.rfc2440 || opt.rfc1991 )
use_mdc = 0; /* override - rfc2440 does not know about MDC */ use_mdc = 0; /* override - rfc2440 does not know about MDC */
memset( &ed, 0, sizeof ed ); memset( &ed, 0, sizeof ed );
ed.len = cfx->datalen; ed.len = cfx->datalen;
ed.extralen = blocksize+2; ed.extralen = blocksize+2;
@ -67,6 +78,14 @@ write_header( cipher_filter_context_t *cfx, IOBUF a )
if ( DBG_HASHING ) if ( DBG_HASHING )
md_start_debug( cfx->mdc_hash, "creatmdc" ); md_start_debug( cfx->mdc_hash, "creatmdc" );
} }
{
char buf[20];
sprintf (buf, "%d %d", ed.mdc_method, cfx->dek->algo);
write_status_text (STATUS_BEGIN_ENCRYPTION, buf);
}
init_packet( &pkt ); init_packet( &pkt );
pkt.pkttype = use_mdc? PKT_ENCRYPTED_MDC : PKT_ENCRYPTED; pkt.pkttype = use_mdc? PKT_ENCRYPTED_MDC : PKT_ENCRYPTED;
pkt.pkt.encrypted = &ed; pkt.pkt.encrypted = &ed;
@ -111,7 +130,6 @@ cipher_filter( void *opaque, int control,
else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */ else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
assert(a); assert(a);
if( !cfx->header ) { if( !cfx->header ) {
write_status( STATUS_BEGIN_ENCRYPTION );
write_header( cfx, a ); write_header( cfx, a );
} }
if( cfx->mdc_hash ) if( cfx->mdc_hash )

View File

@ -61,8 +61,18 @@ do_delete_key( const char *username, int secret, int *r_sec_avail )
*r_sec_avail = 0; *r_sec_avail = 0;
/* search the userid */ /* search the userid */
rc = secret? find_secret_keyblock_byname( &kbpos, username ) if (secret
: find_keyblock_byname( &kbpos, username ); && classify_user_id (username, keyid, NULL, NULL, NULL) == 11) {
/* if the user supplied a long keyID we use the direct search
methods which allows us to delete a key if the
corresponding secret key is missing */
rc = find_secret_keyblock_direct (&kbpos, keyid);
}
else if (secret)
rc = find_secret_keyblock_byname (&kbpos, username);
else
rc = find_keyblock_byname (&kbpos, username);
if( rc ) { if( rc ) {
log_error(_("%s: user not found\n"), username ); log_error(_("%s: user not found\n"), username );
write_status_text( STATUS_DELETE_PROBLEM, "1" ); write_status_text( STATUS_DELETE_PROBLEM, "1" );

View File

@ -299,6 +299,8 @@ encode_crypt( const char *filename, STRLIST remusr )
} }
else else
cfx.dek->algo = opt.def_cipher_algo; cfx.dek->algo = opt.def_cipher_algo;
cfx.dek->use_mdc = select_mdc_from_pklist (pk_list);
make_session_key( cfx.dek ); make_session_key( cfx.dek );
if( DBG_CIPHER ) if( DBG_CIPHER )
log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen ); log_hexdump("DEK is: ", cfx.dek->key, cfx.dek->keylen );
@ -428,6 +430,9 @@ encrypt_filter( void *opaque, int control,
} }
else else
efx->cfx.dek->algo = opt.def_cipher_algo; efx->cfx.dek->algo = opt.def_cipher_algo;
efx->cfx.dek->use_mdc = select_mdc_from_pklist (efx->pk_list);
make_session_key( efx->cfx.dek ); make_session_key( efx->cfx.dek );
if( DBG_CIPHER ) if( DBG_CIPHER )
log_hexdump("DEK is: ", log_hexdump("DEK is: ",

View File

@ -542,55 +542,8 @@ get_seckey( PKT_secret_key *sk, u32 *keyid )
int int
seckey_available( u32 *keyid ) seckey_available( u32 *keyid )
{ {
#if 0 KBPOS dummy_kbpos;
int rc; return find_secret_keyblock_direct (&dummy_kbpos, keyid)? G10ERR_NO_SECKEY:0;
struct getkey_ctx_s ctx;
KBNODE kb = NULL;
memset( &ctx, 0, sizeof ctx );
ctx.exact = 1; /* use the key ID exactly as given */
ctx.not_allocated = 1;
ctx.nitems = 1;
ctx.items[0].mode = 11;
ctx.items[0].keyid[0] = keyid[0];
ctx.items[0].keyid[1] = keyid[1];
rc = lookup( &ctx, &kb, 1 );
get_seckey_end( &ctx );
release_kbnode ( kb );
return rc;
#endif
int rc;
int found = 0;
int oldmode = set_packet_list_mode (0);
KBNODE keyblock = NULL;
KBPOS kbpos;
rc = enum_keyblocks ( 5, &kbpos, NULL );
if ( !rc ) {
while ( !(rc = enum_keyblocks (1, &kbpos, &keyblock)) ) {
KBNODE k;
for (k=keyblock; k; k = k->next ) {
if ( k->pkt->pkttype == PKT_SECRET_KEY
|| k->pkt->pkttype == PKT_SECRET_SUBKEY ) {
u32 aki[2];
keyid_from_sk (k->pkt->pkt.secret_key, aki );
if( aki[1] == keyid[1] && aki[0] == keyid[0] ) {
found = 1;
goto leave;
}
}
}
release_kbnode (keyblock); keyblock = NULL;
}
}
if( rc && rc != -1 )
log_error ("enum_keyblocks failed: %s\n", g10_errstr(rc));
leave:
release_kbnode (keyblock);
enum_keyblocks ( 2, &kbpos, NULL );
set_packet_list_mode (oldmode);
return found? 0 : G10ERR_NO_SECKEY;
} }
@ -1458,7 +1411,7 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated )
* from the hashed list but if there are no such preferences, we * from the hashed list but if there are no such preferences, we
* try to get them from the unhashed list. There is no risk with * try to get them from the unhashed list. There is no risk with
* that, because our implementation comes only with strong * that, because our implementation comes only with strong
* algorithms and it woulkd be fruitless for an attacker to insert * algorithms and it would be fruitless for an attacker to insert
* an weak algorithm. */ * an weak algorithm. */
p = parse_sig_subpkt2 ( sig, SIGSUBPKT_PREF_SYM, &n ); p = parse_sig_subpkt2 ( sig, SIGSUBPKT_PREF_SYM, &n );
sym = p; nsym = p?n:0; sym = p; nsym = p?n:0;
@ -1490,6 +1443,18 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated )
uid->prefs[n].value = 0; uid->prefs[n].value = 0;
} }
/* see whether we have the MDC feature */
uid->mdc_feature = 0;
p = parse_sig_subpkt (sig->hashed, SIGSUBPKT_FEATURES, &n);
if (!p)
n=0;
for (; n; n--, p++) {
if (*p == 1) {
uid->mdc_feature = 1;
break;
}
}
} }
static void static void
@ -1846,6 +1811,7 @@ merge_selfsigs( KBNODE keyblock )
int revoked; int revoked;
PKT_public_key *main_pk; PKT_public_key *main_pk;
prefitem_t *prefs; prefitem_t *prefs;
int mdc_feature;
if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY ) { if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY ) {
if (keyblock->pkt->pkttype == PKT_SECRET_KEY ) { if (keyblock->pkt->pkttype == PKT_SECRET_KEY ) {
@ -1890,12 +1856,15 @@ merge_selfsigs( KBNODE keyblock )
* use reference counting to optimize the preference lists storage. * use reference counting to optimize the preference lists storage.
* FIXME: it might be better to use the intersection of * FIXME: it might be better to use the intersection of
* all preferences. * all preferences.
* Do a similar thing for the MDC feature flag.
*/ */
prefs = NULL; prefs = NULL;
mdc_feature = 0;
for (k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; k = k->next) { for (k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; k = k->next) {
if (k->pkt->pkttype == PKT_USER_ID if (k->pkt->pkttype == PKT_USER_ID
&& k->pkt->pkt.user_id->is_primary) { && k->pkt->pkt.user_id->is_primary) {
prefs = k->pkt->pkt.user_id->prefs; prefs = k->pkt->pkt.user_id->prefs;
mdc_feature = k->pkt->pkt.user_id->mdc_feature;
break; break;
} }
} }
@ -1906,6 +1875,7 @@ merge_selfsigs( KBNODE keyblock )
if (pk->prefs) if (pk->prefs)
m_free (pk->prefs); m_free (pk->prefs);
pk->prefs = copy_prefs (prefs); pk->prefs = copy_prefs (prefs);
pk->mdc_feature = mdc_feature;
} }
} }

View File

@ -385,12 +385,13 @@ dump_kbnode( KBNODE node )
else if( node->pkt->pkttype == PKT_PUBLIC_KEY else if( node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) { || node->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
PKT_public_key *pk = node->pkt->pkt.public_key; PKT_public_key *pk = node->pkt->pkt.public_key;
fprintf(stderr, " keyid=%08lX a=%d u=%d %c%c%c\n", fprintf(stderr, " keyid=%08lX a=%d u=%d %c%c%c%c\n",
(ulong)keyid_from_pk( pk, NULL ), (ulong)keyid_from_pk( pk, NULL ),
pk->pubkey_algo, pk->pubkey_usage, pk->pubkey_algo, pk->pubkey_usage,
pk->has_expired? 'e':'.', pk->has_expired? 'e':'.',
pk->is_revoked? 'r':'.', pk->is_revoked? 'r':'.',
pk->is_valid? 'v':'.' ); pk->is_valid? 'v':'.',
pk->mdc_feature? 'm':'.');
} }
else else
fputs("\n", stderr); fputs("\n", stderr);

View File

@ -124,6 +124,7 @@ int check_signatures_trust( PKT_signature *sig );
void release_pk_list( PK_LIST pk_list ); void release_pk_list( PK_LIST pk_list );
int build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use ); int build_pk_list( STRLIST remusr, PK_LIST *ret_pk_list, unsigned use );
int select_algo_from_prefs( PK_LIST pk_list, int preftype ); int select_algo_from_prefs( PK_LIST pk_list, int preftype );
int select_mdc_from_pklist (PK_LIST pk_list);
/*-- skclist.c --*/ /*-- skclist.c --*/
void release_sk_list( SK_LIST sk_list ); void release_sk_list( SK_LIST sk_list );
@ -218,15 +219,12 @@ int add_keyblock_resource( const char *resname, int force, int secret );
const char *keyblock_resource_name( KBPOS *kbpos ); const char *keyblock_resource_name( KBPOS *kbpos );
int get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos ); int get_keyblock_handle( const char *filename, int secret, KBPOS *kbpos );
char *get_writable_keyblock_file( int secret ); char *get_writable_keyblock_file( int secret );
int locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr,
int fprlen, int secret );
int locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid,
int shortkid, int secret );
int find_keyblock( PUBKEY_FIND_INFO info, KBPOS *kbpos ); int find_keyblock( PUBKEY_FIND_INFO info, KBPOS *kbpos );
int find_keyblock_byname( KBPOS *kbpos, const char *username ); int find_keyblock_byname( KBPOS *kbpos, const char *username );
int find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk ); int find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk );
int find_keyblock_bysk( KBPOS *kbpos, PKT_secret_key *sk ); int find_secret_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk );
int find_secret_keyblock_byname( KBPOS *kbpos, const char *username ); int find_secret_keyblock_byname( KBPOS *kbpos, const char *username );
int find_secret_keyblock_direct (KBPOS *kbpos, u32 *keyid);
int lock_keyblock( KBPOS *kbpos ); int lock_keyblock( KBPOS *kbpos );
void unlock_keyblock( KBPOS *kbpos ); void unlock_keyblock( KBPOS *kbpos );
int read_keyblock( KBPOS *kbpos, KBNODE *ret_root ); int read_keyblock( KBPOS *kbpos, KBNODE *ret_root );

View File

@ -650,10 +650,19 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
have_commands = 1; have_commands = 1;
} }
/* get the public key */
rc = get_keyblock_byname( &keyblock, &keyblockpos, username );
if( rc )
goto leave;
if( fix_keyblock( keyblock ) )
modified++;
if( collapse_uids( &keyblock ) )
modified++;
if( !sign_mode ) { if( !sign_mode ) {/* see whether we have a matching secret key */
/* first try to locate it as secret key */ PKT_public_key *pk = keyblock->pkt->pkt.public_key;
rc = find_secret_keyblock_byname( &sec_keyblockpos, username );
rc = find_secret_keyblock_bypk( &sec_keyblockpos, pk );
if( !rc ) { if( !rc ) {
rc = read_keyblock( &sec_keyblockpos, &sec_keyblock ); rc = read_keyblock( &sec_keyblockpos, &sec_keyblock );
if( rc ) { if( rc ) {
@ -667,17 +676,7 @@ keyedit_menu( const char *username, STRLIST locusr, STRLIST commands,
} }
} }
/* and now get the public key */ if( sec_keyblock ) {
rc = get_keyblock_byname( &keyblock, &keyblockpos, username );
if( rc )
goto leave;
if( fix_keyblock( keyblock ) )
modified++;
if( collapse_uids( &keyblock ) )
modified++;
if( sec_keyblock ) { /* check that they match */
/* fixme: check that they both match */
tty_printf(_("Secret key is available.\n")); tty_printf(_("Secret key is available.\n"));
} }
@ -1118,6 +1117,8 @@ show_prefs (PKT_user_id *uid, int verbose)
prefs[i].type == PREFTYPE_ZIP ? 'Z':'?', prefs[i].type == PREFTYPE_ZIP ? 'Z':'?',
prefs[i].value); prefs[i].value);
} }
if (uid->mdc_feature)
tty_printf (" [mdc]");
tty_printf("\n"); tty_printf("\n");
} }
} }

View File

@ -280,6 +280,30 @@ keygen_get_std_prefs ()
} }
static void
add_feature_mdc (PKT_signature *sig)
{
const byte *s;
size_t i, n;
char *buf;
s = parse_sig_subpkt (sig->hashed, SIGSUBPKT_FEATURES, &n );
if (!s)
n = 0;
for (i=0; i < n; i++ ) {
if (s[i] == 1)
return; /* already set */
}
buf = m_alloc (n+1);
buf[0] = 1; /* MDC feature */
memcpy (buf+1, s, n);
build_sig_subpkt (sig, SIGSUBPKT_FEATURES, buf, n+1);
m_free (buf);
}
int int
keygen_upd_std_prefs( PKT_signature *sig, void *opaque ) keygen_upd_std_prefs( PKT_signature *sig, void *opaque )
{ {
@ -298,6 +322,10 @@ keygen_upd_std_prefs( PKT_signature *sig, void *opaque )
build_sig_subpkt (sig, SIGSUBPKT_PREF_COMPR, zip_prefs, nzip_prefs); build_sig_subpkt (sig, SIGSUBPKT_PREF_COMPR, zip_prefs, nzip_prefs);
else else
delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_COMPR); delete_sig_subpkt (sig->hashed, SIGSUBPKT_PREF_COMPR);
/* Make sure that the MDC feature flag is set */
add_feature_mdc (sig);
return 0; return 0;
} }

View File

@ -145,6 +145,7 @@ typedef struct {
int is_primary; int is_primary;
int is_revoked; int is_revoked;
prefitem_t *prefs; /* list of preferences (may be NULL)*/ prefitem_t *prefs; /* list of preferences (may be NULL)*/
int mdc_feature;
u32 created; /* according to the self-signature */ u32 created; /* according to the self-signature */
char name[1]; char name[1];
} PKT_user_id; } PKT_user_id;
@ -172,6 +173,7 @@ typedef struct {
u32 main_keyid[2]; /* keyid of the primary key */ u32 main_keyid[2]; /* keyid of the primary key */
u32 keyid[2]; /* calculated by keyid_from_pk() */ u32 keyid[2]; /* calculated by keyid_from_pk() */
prefitem_t *prefs; /* list of preferences (may be NULL) */ prefitem_t *prefs; /* list of preferences (may be NULL) */
int mdc_feature; /* mdc feature set */
byte *namehash; /* if != NULL: found by this name */ byte *namehash; /* if != NULL: found by this name */
PKT_user_id *user_id; /* if != NULL: found by that uid */ PKT_user_id *user_id; /* if != NULL: found by that uid */
MPI pkey[PUBKEY_MAX_NPKEY]; MPI pkey[PUBKEY_MAX_NPKEY];
@ -303,6 +305,7 @@ typedef enum {
SIGSUBPKT_KEY_FLAGS =27, /* key flags */ SIGSUBPKT_KEY_FLAGS =27, /* key flags */
SIGSUBPKT_SIGNERS_UID =28, /* signer's user id */ SIGSUBPKT_SIGNERS_UID =28, /* signer's user id */
SIGSUBPKT_REVOC_REASON =29, /* reason for revocation */ SIGSUBPKT_REVOC_REASON =29, /* reason for revocation */
SIGSUBPKT_FEATURES =30, /* feature flags */
SIGSUBPKT_PRIV_VERIFY_CACHE =101, /* cache verification result */ SIGSUBPKT_PRIV_VERIFY_CACHE =101, /* cache verification result */
SIGSUBPKT_FLAG_CRITICAL=128 SIGSUBPKT_FLAG_CRITICAL=128
@ -320,7 +323,7 @@ int list_packets( IOBUF a );
int set_packet_list_mode( int mode ); int set_packet_list_mode( int mode );
#if DEBUG_PARSE_PACKET #if DEBUG_PARSE_PACKET
int dbg_search_packet( IOBUF inp, PACKET *pkt, int pkttype, off_t *retpos, int dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos,
const char* file, int lineno ); const char* file, int lineno );
int dbg_parse_packet( IOBUF inp, PACKET *ret_pkt, int dbg_parse_packet( IOBUF inp, PACKET *ret_pkt,
const char* file, int lineno ); const char* file, int lineno );
@ -330,8 +333,8 @@ int dbg_copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff,
const char* file, int lineno ); const char* file, int lineno );
int dbg_skip_some_packets( IOBUF inp, unsigned n, int dbg_skip_some_packets( IOBUF inp, unsigned n,
const char* file, int lineno ); const char* file, int lineno );
#define search_packet( a,b,c,d ) \ #define search_packet( a,b,c ) \
dbg_search_packet( (a), (b), (c), (d), __FILE__, __LINE__ ) dbg_search_packet( (a), (b), (c), __FILE__, __LINE__ )
#define parse_packet( a, b ) \ #define parse_packet( a, b ) \
dbg_parse_packet( (a), (b), __FILE__, __LINE__ ) dbg_parse_packet( (a), (b), __FILE__, __LINE__ )
#define copy_all_packets( a,b ) \ #define copy_all_packets( a,b ) \
@ -341,7 +344,7 @@ int dbg_skip_some_packets( IOBUF inp, unsigned n,
#define skip_some_packets( a,b ) \ #define skip_some_packets( a,b ) \
dbg_skip_some_packets((a),(b), __FILE__, __LINE__ ) dbg_skip_some_packets((a),(b), __FILE__, __LINE__ )
#else #else
int search_packet( IOBUF inp, PACKET *pkt, int pkttype, off_t *retpos ); int search_packet( IOBUF inp, PACKET *pkt, off_t *retpos );
int parse_packet( IOBUF inp, PACKET *ret_pkt); int parse_packet( IOBUF inp, PACKET *ret_pkt);
int copy_all_packets( IOBUF inp, IOBUF out ); int copy_all_packets( IOBUF inp, IOBUF out );
int copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff ); int copy_some_packets( IOBUF inp, IOBUF out, off_t stopoff );

View File

@ -38,7 +38,7 @@
static int mpi_print_mode = 0; static int mpi_print_mode = 0;
static int list_mode = 0; static int list_mode = 0;
static int parse( IOBUF inp, PACKET *pkt, int reqtype, static int parse( IOBUF inp, PACKET *pkt, int onlykeypkts,
off_t *retpos, int *skip, IOBUF out, int do_skip off_t *retpos, int *skip, IOBUF out, int do_skip
#ifdef DEBUG_PARSE_PACKET #ifdef DEBUG_PARSE_PACKET
,const char *dbg_w, const char *dbg_f, int dbg_l ,const char *dbg_w, const char *dbg_f, int dbg_l
@ -154,28 +154,28 @@ parse_packet( IOBUF inp, PACKET *pkt )
#endif #endif
/**************** /****************
* Like parse packet, but only return packets of the given type. * Like parse packet, but only return secret or public (sub)key packets.
*/ */
#ifdef DEBUG_PARSE_PACKET #ifdef DEBUG_PARSE_PACKET
int int
dbg_search_packet( IOBUF inp, PACKET *pkt, int pkttype, off_t *retpos, dbg_search_packet( IOBUF inp, PACKET *pkt, off_t *retpos,
const char *dbg_f, int dbg_l ) const char *dbg_f, int dbg_l )
{ {
int skip, rc; int skip, rc;
do { do {
rc = parse( inp, pkt, pkttype, retpos, &skip, NULL, 0, "search", dbg_f, dbg_l ); rc = parse( inp, pkt, 1, retpos, &skip, NULL, 0, "search", dbg_f, dbg_l );
} while( skip ); } while( skip );
return rc; return rc;
} }
#else #else
int int
search_packet( IOBUF inp, PACKET *pkt, int pkttype, off_t *retpos ) search_packet( IOBUF inp, PACKET *pkt, off_t *retpos )
{ {
int skip, rc; int skip, rc;
do { do {
rc = parse( inp, pkt, pkttype, retpos, &skip, NULL, 0 ); rc = parse( inp, pkt, 1, retpos, &skip, NULL, 0 );
} while( skip ); } while( skip );
return rc; return rc;
} }
@ -277,14 +277,14 @@ skip_some_packets( IOBUF inp, unsigned n )
/**************** /****************
* Parse packet. Set the variable skip points to to 1 if the packet * Parse packet. Set the variable skip points to 1 if the packet
* should be skipped; this is the case if either there is a * should be skipped; this is the case if either ONLYKEYPKTS is set
* requested packet type and the parsed packet doesn't match or the * and the parsed packet isn't one or the
* packet-type is 0, indicating deleted stuff. * packet-type is 0, indicating deleted stuff.
* if OUT is not NULL, a special copymode is used. * if OUT is not NULL, a special copymode is used.
*/ */
static int static int
parse( IOBUF inp, PACKET *pkt, int reqtype, off_t *retpos, parse( IOBUF inp, PACKET *pkt, int onlykeypkts, off_t *retpos,
int *skip, IOBUF out, int do_skip int *skip, IOBUF out, int do_skip
#ifdef DEBUG_PARSE_PACKET #ifdef DEBUG_PARSE_PACKET
,const char *dbg_w, const char *dbg_f, int dbg_l ,const char *dbg_w, const char *dbg_f, int dbg_l
@ -375,7 +375,12 @@ parse( IOBUF inp, PACKET *pkt, int reqtype, off_t *retpos,
goto leave; goto leave;
} }
if( do_skip || !pkttype || (reqtype && pkttype != reqtype) ) { if( do_skip
|| !pkttype
|| (onlykeypkts && pkttype != PKT_PUBLIC_SUBKEY
&& pkttype != PKT_PUBLIC_KEY
&& pkttype != PKT_SECRET_SUBKEY
&& pkttype != PKT_SECRET_KEY ) ) {
skip_rest(inp, pktlen); skip_rest(inp, pktlen);
*skip = 1; *skip = 1;
rc = 0; rc = 0;
@ -856,6 +861,11 @@ dump_sig_subpkt( int hashed, int type, int critical,
printf("%02X", buffer[i] ); printf("%02X", buffer[i] );
} }
break; break;
case SIGSUBPKT_FEATURES:
fputs ( "features:", stdout );
for( i=0; i < length; i++ )
printf(" %d", buffer[i] );
break;
case SIGSUBPKT_PRIV_VERIFY_CACHE: case SIGSUBPKT_PRIV_VERIFY_CACHE:
p = "verification cache"; p = "verification cache";
break; break;
@ -903,6 +913,7 @@ parse_one_sig_subpkt( const byte *buffer, size_t n, int type )
case SIGSUBPKT_PREF_HASH: case SIGSUBPKT_PREF_HASH:
case SIGSUBPKT_PREF_COMPR: case SIGSUBPKT_PREF_COMPR:
case SIGSUBPKT_POLICY: case SIGSUBPKT_POLICY:
case SIGSUBPKT_FEATURES:
return 0; return 0;
case SIGSUBPKT_PRIMARY_UID: case SIGSUBPKT_PRIMARY_UID:
if ( n != 1 ) if ( n != 1 )
@ -944,6 +955,7 @@ can_handle_critical( const byte *buffer, size_t n, int type )
case SIGSUBPKT_PREF_COMPR: case SIGSUBPKT_PREF_COMPR:
case SIGSUBPKT_KEY_FLAGS: case SIGSUBPKT_KEY_FLAGS:
case SIGSUBPKT_PRIMARY_UID: case SIGSUBPKT_PRIMARY_UID:
case SIGSUBPKT_FEATURES:
return 1; return 1;
case SIGSUBPKT_POLICY: /* Is it enough to show the policy? */ case SIGSUBPKT_POLICY: /* Is it enough to show the policy? */

View File

@ -1146,4 +1146,29 @@ select_algo_from_prefs( PK_LIST pk_list, int preftype )
return i; return i;
} }
/*
* Select the MDC flag from the pk_list. We can only use MDC if all recipients
* support this feature
*/
int
select_mdc_from_pklist (PK_LIST pk_list)
{
PK_LIST pkr;
if( !pk_list )
return 0;
for (pkr = pk_list; pkr; pkr = pkr->next) {
int mdc;
if (pkr->pk->user_id) /* selected by user ID */
mdc = pkr->pk->user_id->mdc_feature;
else
mdc = pkr->pk->mdc_feature;
if (!mdc)
return 0; /* at least on recipeint does not support it */
}
return 1; /* can be used */
}

View File

@ -84,11 +84,12 @@ static RESTBL resource_table[MAX_RESOURCES];
static int default_public_resource; static int default_public_resource;
static int default_secret_resource; static int default_secret_resource;
static int search( PACKET *pkt, KBPOS *kbpos, int secret ); static int search (PKT_public_key *req_pk, u32 *req_keyid,
KBPOS *kbpos, int secret);
static int keyring_search( PACKET *pkt, KBPOS *kbpos, IOBUF iobuf, static int keyring_search (PKT_public_key *req_pk, u32 *req_keyid,
const char *fname ); KBPOS *kbpos, IOBUF iobuf, const char *fname );
static int keyring_read( KBPOS *kbpos, KBNODE *ret_root ); static int keyring_read( KBPOS *kbpos, KBNODE *ret_root );
static int keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs ); static int keyring_enum( KBPOS *kbpos, KBNODE *ret_root, int skipsigs );
static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root ); static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root );
@ -97,7 +98,7 @@ static int keyring_copy( KBPOS *kbpos, int mode, KBNODE root );
static int do_gdbm_store( KBPOS *kbpos, KBNODE root, int update ); static int do_gdbm_store( KBPOS *kbpos, KBNODE root, int update );
static int do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos, static int do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos,
const byte *fpr, int fprlen ); const byte *fpr, int fprlen );
static int do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid ); /*static int do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid );*/
static int do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root ); static int do_gdbm_read( KBPOS *kbpos, KBNODE *ret_root );
static int do_gdbm_enum( KBPOS *kbpos, KBNODE *ret_root ); static int do_gdbm_enum( KBPOS *kbpos, KBNODE *ret_root );
#endif #endif
@ -464,7 +465,7 @@ get_writable_keyblock_file( int secret )
* Returns: 0 if found, -1 if not found or an errorcode. * Returns: 0 if found, -1 if not found or an errorcode.
*/ */
static int static int
search( PACKET *pkt, KBPOS *kbpos, int secret ) search (PKT_public_key *req_pk, u32 *req_keyid, KBPOS *kbpos, int secret)
{ {
int i, rc, last_rc=-1; int i, rc, last_rc=-1;
@ -472,18 +473,23 @@ search( PACKET *pkt, KBPOS *kbpos, int secret )
if( resource_table[i].used && !resource_table[i].secret == !secret ) { if( resource_table[i].used && !resource_table[i].secret == !secret ) {
switch( resource_table[i].rt ) { switch( resource_table[i].rt ) {
case rt_RING: case rt_RING:
rc = keyring_search( pkt, kbpos, resource_table[i].iobuf, rc = keyring_search (req_pk, req_keyid,
resource_table[i].fname ); kbpos, resource_table[i].iobuf,
break; resource_table[i].fname );
#ifdef HAVE_LIBGDBM
break;
#ifdef HAVE_LIBGDBM
case rt_GDBM: { case rt_GDBM: {
PKT_public_key *req_pk = pkt->pkt.public_key;
byte fpr[20]; byte fpr[20];
size_t fprlen; size_t fprlen;
fingerprint_from_pk( req_pk, fpr, &fprlen ); if (!req_pk)
rc = do_gdbm_locate( resource_table[i].dbf, rc = G10ERR_UNSUPPORTED;
kbpos, fpr, fprlen ); else {
fingerprint_from_pk( req_pk, fpr, &fprlen );
rc = do_gdbm_locate( resource_table[i].dbf,
kbpos, fpr, fprlen );
}
} }
break; break;
#endif #endif
@ -514,20 +520,12 @@ search( PACKET *pkt, KBPOS *kbpos, int secret )
int int
find_keyblock_byname( KBPOS *kbpos, const char *username ) find_keyblock_byname( KBPOS *kbpos, const char *username )
{ {
PACKET pkt;
PKT_public_key *pk = m_alloc_clear( sizeof *pk ); PKT_public_key *pk = m_alloc_clear( sizeof *pk );
int rc; int rc;
rc = get_pubkey_byname( NULL, pk, username, NULL ); rc = get_pubkey_byname( NULL, pk, username, NULL );
if( rc ) { if (!rc)
free_public_key(pk); rc = search( pk, NULL, kbpos, 0 );
return rc;
}
init_packet( &pkt );
pkt.pkttype = PKT_PUBLIC_KEY;
pkt.pkt.public_key = pk;
rc = search( &pkt, kbpos, 0 );
free_public_key(pk); free_public_key(pk);
return rc; return rc;
} }
@ -540,30 +538,22 @@ find_keyblock_byname( KBPOS *kbpos, const char *username )
int int
find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk ) find_keyblock_bypk( KBPOS *kbpos, PKT_public_key *pk )
{ {
PACKET pkt;
int rc; int rc;
init_packet( &pkt ); rc = search( pk, NULL, kbpos, 0 );
pkt.pkttype = PKT_PUBLIC_KEY;
pkt.pkt.public_key = pk;
rc = search( &pkt, kbpos, 0 );
return rc; return rc;
} }
/**************** /****************
* Combined function to search for a key and get the position * Combined function to search for a secret key and get the position
* of the keyblock. * of the keyblock.
*/ */
int int
find_keyblock_bysk( KBPOS *kbpos, PKT_secret_key *sk ) find_secret_keyblock_bypk (KBPOS *kbpos, PKT_public_key *pk)
{ {
PACKET pkt;
int rc; int rc;
init_packet( &pkt ); rc = search (pk, NULL, kbpos, 1);
pkt.pkttype = PKT_SECRET_KEY;
pkt.pkt.secret_key = sk;
rc = search( &pkt, kbpos, 0 );
return rc; return rc;
} }
@ -575,113 +565,27 @@ find_keyblock_bysk( KBPOS *kbpos, PKT_secret_key *sk )
int int
find_secret_keyblock_byname( KBPOS *kbpos, const char *username ) find_secret_keyblock_byname( KBPOS *kbpos, const char *username )
{ {
PACKET pkt; PKT_public_key *pk = m_alloc_clear( sizeof *pk );
PKT_secret_key *sk = m_alloc_clear( sizeof *sk );
int rc; int rc;
rc = get_seckey_byname( sk, username, 0 ); rc = get_pubkey_byname( NULL, pk, username, NULL );
if( rc ) { if (!rc)
free_secret_key(sk); rc = search (pk, NULL, kbpos, 1);
return rc; free_public_key (pk);
}
init_packet( &pkt );
pkt.pkttype = PKT_SECRET_KEY;
pkt.pkt.secret_key = sk;
rc = search( &pkt, kbpos, 1 );
free_secret_key(sk);
return rc; return rc;
} }
/*
/**************** * This function locates the secret keyblock without doing a public
* Locate a keyblock in a database which is capable of direct access * keyring check fist. It is useful in certain situations and much
* Put all information into KBPOS, which can be later be to access this * faster than the generic solution.
* key block.
* This function looks into all registered keyblock sources.
*
* Returns: 0 if found,
* -1 if not found
* G10ERR_UNSUPPORTED if no resource is able to handle this
* or another errorcode.
*/ */
int int
locate_keyblock_by_fpr( KBPOS *kbpos, const byte *fpr, int fprlen, int secret ) find_secret_keyblock_direct (KBPOS *kbpos, u32 *keyid)
{ {
RESTBL *rentry; int rc;
int i, rc, any=0, last_rc=-1; rc = search (NULL, keyid, kbpos, 1);
return rc;
for(i=0, rentry = resource_table; i < MAX_RESOURCES; i++, rentry++ ) {
if( rentry->used && !rentry->secret == !secret ) {
kbpos->rt = rentry->rt;
switch( rentry->rt ) {
#ifdef HAVE_LIBGDBM
case rt_GDBM:
any = 1;
rc = do_gdbm_locate( rentry->dbf, kbpos, fpr, fprlen );
break;
#endif
default:
rc = G10ERR_UNSUPPORTED;
break;
}
if( !rc ) {
kbpos->resno = i;
kbpos->fp = NULL;
return 0;
}
else if( rc != -1 && rc != G10ERR_UNSUPPORTED ) {
log_error("error searching resource %d: %s\n",
i, g10_errstr(rc));
last_rc = rc;
}
}
}
return (last_rc == -1 && !any)? G10ERR_UNSUPPORTED : last_rc;
}
int
locate_keyblock_by_keyid( KBPOS *kbpos, u32 *keyid, int shortkid, int secret )
{
RESTBL *rentry;
int i, rc, any=0, last_rc=-1;
if( shortkid )
return G10ERR_UNSUPPORTED;
for(i=0, rentry = resource_table; i < MAX_RESOURCES; i++, rentry++ ) {
if( rentry->used && !rentry->secret == !secret ) {
kbpos->rt = rentry->rt;
switch( rentry->rt ) {
#ifdef HAVE_LIBGDBM
case rt_GDBM:
any = 1;
rc = do_gdbm_locate_by_keyid( rentry->dbf, kbpos, keyid );
break;
#endif
default:
rc = G10ERR_UNSUPPORTED;
break;
}
if( !rc ) {
kbpos->resno = i;
kbpos->fp = NULL;
return 0;
}
else if( rc != -1 && rc != G10ERR_UNSUPPORTED ) {
log_error("error searching resource %d: %s\n",
i, g10_errstr(rc));
last_rc = rc;
}
}
}
return (last_rc == -1 && !any)? G10ERR_UNSUPPORTED : last_rc;
} }
@ -1065,21 +969,16 @@ scan_user_file_read( SCAN_USER_HANDLE hd, byte *fpr )
****************************************************************/ ****************************************************************/
static int static int
cmp_seckey( PKT_secret_key *req_sk, PKT_secret_key *sk ) cmp_seckey( PKT_public_key *req_pk, PKT_secret_key *sk )
{ {
int n,i; int n,i;
assert( req_sk->pubkey_algo == sk->pubkey_algo ); if (req_pk->pubkey_algo != sk->pubkey_algo)
return -1;
n = pubkey_get_nskey( req_sk->pubkey_algo ); n = pubkey_get_npkey (req_pk->pubkey_algo);
for(i=0; i < n; i++ ) { for (i=0; i < n; i++ ) {
/* Note: becuase v4 protected keys have nothing in the if( mpi_cmp (req_pk->pkey[i], sk->skey[i]) )
* mpis except for the first one, we skip all NULL MPIs.
* This might not be always correct in cases where the both
* keys do not match in their secret parts but we can ignore that
* because the need for this function is quite ugly. */
if( req_sk->skey[1] && sk->skey[i]
&& mpi_cmp( req_sk->skey[i], sk->skey[i] ) )
return -1; return -1;
} }
return 0; return 0;
@ -1104,16 +1003,15 @@ cmp_pubkey( PKT_public_key *req_pk, PKT_public_key *pk )
* search one keyring, return 0 if found, -1 if not found or an errorcode. * search one keyring, return 0 if found, -1 if not found or an errorcode.
*/ */
static int static int
keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname ) keyring_search( PKT_public_key *req_pk, u32 *req_keyid,
KBPOS *kbpos, IOBUF iobuf, const char *fname )
{ {
int rc; int rc;
PACKET pkt; PACKET pkt;
int save_mode; int save_mode;
off_t offset; off_t offset, main_offset;
int pkttype = req->pkttype;
PKT_public_key *req_pk = req->pkt.public_key;
PKT_secret_key *req_sk = req->pkt.secret_key;
assert (!!req_pk ^ !!req_keyid); /* exactly one must be specified */
init_packet(&pkt); init_packet(&pkt);
save_mode = set_packet_list_mode(0); save_mode = set_packet_list_mode(0);
kbpos->rt = rt_RING; kbpos->rt = rt_RING;
@ -1135,29 +1033,57 @@ keyring_search( PACKET *req, KBPOS *kbpos, IOBUF iobuf, const char *fname )
} }
#endif #endif
while( !(rc=search_packet(iobuf, &pkt, pkttype, &offset)) ) { main_offset = 0;
if( pkt.pkttype == PKT_SECRET_KEY ) { while ( !(rc=search_packet(iobuf, &pkt, &offset)) ) {
if (pkt.pkttype == PKT_PUBLIC_KEY || pkt.pkttype == PKT_SECRET_KEY) {
main_offset = offset;
}
if (pkt.pkttype == PKT_SECRET_KEY || pkt.pkttype == PKT_SECRET_SUBKEY) {
PKT_secret_key *sk = pkt.pkt.secret_key; PKT_secret_key *sk = pkt.pkt.secret_key;
if( req_sk->timestamp == sk->timestamp if (req_keyid) {
&& req_sk->pubkey_algo == sk->pubkey_algo u32 aki[2];
&& !cmp_seckey( req_sk, sk) )
break; /* found */ keyid_from_sk (sk, aki);
if (aki[0] == req_keyid[0] && aki[1] == req_keyid[1])
break; /* found */
}
else {
/* We can't compare the timestamps here because they
might differ */
if( !cmp_seckey (req_pk, sk) )
break; /* found */
}
} }
else if( pkt.pkttype == PKT_PUBLIC_KEY ) { else if (pkt.pkttype == PKT_PUBLIC_KEY
|| pkt.pkttype == PKT_PUBLIC_SUBKEY) {
PKT_public_key *pk = pkt.pkt.public_key; PKT_public_key *pk = pkt.pkt.public_key;
if( req_pk->timestamp == pk->timestamp if (req_keyid) {
&& req_pk->pubkey_algo == pk->pubkey_algo u32 aki[2];
&& !cmp_pubkey( req_pk, pk ) )
break; /* found */ keyid_from_pk (pk, aki);
if (aki[0] == req_keyid[0] && aki[1] == req_keyid[1])
break; /* found */
}
else {
if( req_pk->timestamp == pk->timestamp
&& req_pk->pubkey_algo == pk->pubkey_algo
&& !cmp_pubkey( req_pk, pk ) )
break; /* found */
}
} }
else else
BUG(); BUG();
free_packet(&pkt); free_packet(&pkt);
} }
if( !rc ) { if( !rc ) {
kbpos->offset = offset; if (pkt.pkttype == PKT_SECRET_SUBKEY
|| pkt.pkttype == PKT_PUBLIC_SUBKEY)
kbpos->offset = main_offset;
else
kbpos->offset = offset;
kbpos->valid = 1; kbpos->valid = 1;
} }
@ -1710,6 +1636,7 @@ do_gdbm_locate( GDBM_FILE dbf, KBPOS *kbpos, const byte *fpr, int fprlen )
* locate by keyid. * locate by keyid.
* FIXME: we must have a way to enumerate thru the list opf fingerprints * FIXME: we must have a way to enumerate thru the list opf fingerprints
*/ */
#if 0 /* not used */
static int static int
do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid ) do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid )
{ {
@ -1752,7 +1679,7 @@ do_gdbm_locate_by_keyid( GDBM_FILE dbf, KBPOS *kbpos, u32 *keyid )
free( content.dptr ); /* can't use m_free() here */ free( content.dptr ); /* can't use m_free() here */
return rc; return rc;
} }
#endif /* not used */
static int static int

View File

@ -551,7 +551,8 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
} }
else { else {
if (!opt.quiet) if (!opt.quiet)
log_info ("no subkey for subkey revocation packet\n"); log_info ("key %08lX: no subkey for subkey revocation packet\n",
(ulong)keyid_from_pk (pk, NULL));
rc = G10ERR_SIG_CLASS; rc = G10ERR_SIG_CLASS;
} }
} }
@ -574,7 +575,9 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
md_close(md); md_close(md);
} }
else { else {
log_info ("no subkey for key signature packet\n"); if (!opt.quiet)
log_info ("key %08lX: no subkey for subkey binding packet\n",
(ulong)keyid_from_pk (pk, NULL));
rc = G10ERR_SIG_CLASS; rc = G10ERR_SIG_CLASS;
} }
} }
@ -607,8 +610,10 @@ check_key_signature2( KBNODE root, KBNODE node, int *is_selfsig,
md_close(md); md_close(md);
} }
else { else {
log_info ("no user ID for key signature packet of class %02x\n", if (!opt.quiet)
sig->sig_class ); log_info ("key %08lX: no user ID for key signature packet "
"of class %02x\n",
(ulong)keyid_from_pk (pk, NULL), sig->sig_class );
rc = G10ERR_SIG_CLASS; rc = G10ERR_SIG_CLASS;
} }
} }

View File

@ -1,3 +1,7 @@
2001-08-30 Werner Koch <wk@gnupg.org>
* cipher.h (DEK): Added use_mdc.
2001-08-24 Werner Koch <wk@gnupg.org> 2001-08-24 Werner Koch <wk@gnupg.org>
* cipher.h (md_write): Made buf arg const. * cipher.h (md_write): Made buf arg const.

View File

@ -64,6 +64,7 @@ typedef struct {
int algo; int algo;
int keylen; int keylen;
int algo_info_printed; int algo_info_printed;
int use_mdc;
byte key[32]; /* this is the largest used keylen (256 bit) */ byte key[32]; /* this is the largest used keylen (256 bit) */
} DEK; } DEK;