aboutsummaryrefslogtreecommitdiffstats
path: root/g10/getkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'g10/getkey.c')
-rw-r--r--g10/getkey.c141
1 files changed, 105 insertions, 36 deletions
diff --git a/g10/getkey.c b/g10/getkey.c
index 598b33b26..c9d1b874b 100644
--- a/g10/getkey.c
+++ b/g10/getkey.c
@@ -358,15 +358,14 @@ getkey_disable_caches()
static void
-pk_from_block ( GETKEY_CTX ctx,
- PKT_public_key *pk, KBNODE keyblock, const char *namehash )
+pk_from_block ( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE keyblock )
{
KBNODE a = ctx->found_key ? ctx->found_key : keyblock;
assert ( a->pkt->pkttype == PKT_PUBLIC_KEY
|| a->pkt->pkttype == PKT_PUBLIC_SUBKEY );
- copy_public_key_new_namehash( pk, a->pkt->pkt.public_key, namehash);
+ copy_public_key ( pk, a->pkt->pkt.public_key );
}
static void
@@ -435,7 +434,7 @@ get_pubkey( PKT_public_key *pk, u32 *keyid )
ctx.req_usage = pk->req_usage;
rc = lookup( &ctx, &kb, 0 );
if ( !rc ) {
- pk_from_block ( &ctx, pk, kb, NULL );
+ pk_from_block ( &ctx, pk, kb );
}
get_pubkey_end( &ctx );
release_kbnode ( kb );
@@ -925,7 +924,7 @@ key_byname( GETKEY_CTX *retctx, STRLIST namelist,
}
rc = lookup( ctx, ret_kb, 0 );
if ( !rc && pk ) {
- pk_from_block ( ctx, pk, *ret_kb, NULL /* FIXME need to get the namehash*/ );
+ pk_from_block ( ctx, pk, *ret_kb );
}
}
@@ -972,7 +971,7 @@ get_pubkey_next( GETKEY_CTX ctx, PKT_public_key *pk, KBNODE *ret_keyblock )
rc = lookup( ctx, ret_keyblock, 0 );
if ( !rc && pk && ret_keyblock )
- pk_from_block ( ctx, pk, *ret_keyblock, NULL );
+ pk_from_block ( ctx, pk, *ret_keyblock );
return rc;
}
@@ -1020,7 +1019,7 @@ get_pubkey_byfprint( PKT_public_key *pk,
memcpy( ctx.items[0].fprint, fprint, fprint_len );
rc = lookup( &ctx, &kb, 0 );
if (!rc && pk )
- pk_from_block ( &ctx, pk, kb, NULL );
+ pk_from_block ( &ctx, pk, kb );
release_kbnode ( kb );
get_pubkey_end( &ctx );
}
@@ -1399,14 +1398,23 @@ merge_keys_and_selfsig( KBNODE keyblock )
}
}
-
+/*
+ * Apply information from SIGNODE (which is the valid self-signature
+ * associated with that UID) to the UIDNODE:
+ * - wether the UID has been revoked
+ * - assumed creation date of the UID
+ * - temporary store the keyflags here
+ * - temporary store the key expiration time here
+ * - mark whether the primary user ID flag hat been set.
+ * - store the preferences
+ */
static void
fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated )
{
PKT_user_id *uid = uidnode->pkt->pkt.user_id;
PKT_signature *sig = signode->pkt->pkt.signature;
- const byte *p;
- size_t n;
+ const byte *p, *sym, *hash, *zip;
+ size_t n, nsym, nhash, nzip;
uid->created = 0; /* not created == invalid */
if ( IS_UID_REV ( sig ) ) {
@@ -1435,7 +1443,7 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated )
}
/* Set the primary user ID flag - we will later wipe out some
- * of them to only have one in out keyblock */
+ * of them to only have one in our keyblock */
uid->is_primary = 0;
p = parse_sig_subpkt ( sig->hashed, SIGSUBPKT_PRIMARY_UID, NULL );
if ( p && *p )
@@ -1445,6 +1453,43 @@ fixup_uidnode ( KBNODE uidnode, KBNODE signode, u32 keycreated )
* there should be no security problem with this.
* For now we only look at the hashed one.
*/
+
+ /* now build the preferences list. We try to get the preferences
+ * 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
+ * that, because our implementation comes only with strong
+ * algorithms and it woulkd be fruitless for an attacker to insert
+ * an weak algorithm. */
+ p = parse_sig_subpkt2 ( sig, SIGSUBPKT_PREF_SYM, &n );
+ sym = p; nsym = p?n:0;
+ p = parse_sig_subpkt2 ( sig, SIGSUBPKT_PREF_HASH, &n );
+ hash = p; nhash = p?n:0;
+ p = parse_sig_subpkt2 ( sig, SIGSUBPKT_PREF_COMPR, &n );
+ zip = p; nzip = p?n:0;
+ if (uid->prefs)
+ m_free (uid->prefs);
+ n = nsym + nhash + nzip;
+ if (!n)
+ uid->prefs = NULL;
+ else {
+ uid->prefs = m_alloc (sizeof (*uid->prefs) * (n+1));
+ n = 0;
+ for (; nsym; nsym--, n++) {
+ uid->prefs[n].type = PREFTYPE_SYM;
+ uid->prefs[n].value = *sym++;
+ }
+ for (; nhash; nhash--, n++) {
+ uid->prefs[n].type = PREFTYPE_HASH;
+ uid->prefs[n].value = *hash++;
+ }
+ for (; nzip; nzip--, n++) {
+ uid->prefs[n].type = PREFTYPE_ZIP;
+ uid->prefs[n].value = *sym++;
+ }
+ uid->prefs[n].type = PREFTYPE_NONE; /* end of list marker */
+ uid->prefs[n].value = 0;
+ }
+
}
static void
@@ -1800,6 +1845,7 @@ merge_selfsigs( KBNODE keyblock )
KBNODE k;
int revoked;
PKT_public_key *main_pk;
+ prefitem_t *prefs;
if ( keyblock->pkt->pkttype != PKT_PUBLIC_KEY ) {
if (keyblock->pkt->pkttype == PKT_SECRET_KEY ) {
@@ -1836,6 +1882,33 @@ merge_selfsigs( KBNODE keyblock )
merge_selfsigs_subkey ( keyblock, k );
}
}
+
+ /* set the preference list of all keys to those of the primary
+ * user ID. Note: we use these preferences when we don't know by
+ * which user ID the key has been selected.
+ * fixme: we should keep atoms of commonly used preferences or
+ * use reference counting to optimize the preference lists storage.
+ * FIXME: it might be better to use the intersection of
+ * all preferences.
+ */
+ prefs = NULL;
+ for (k=keyblock; k && k->pkt->pkttype != PKT_PUBLIC_SUBKEY; k = k->next) {
+ if (k->pkt->pkttype == PKT_USER_ID
+ && k->pkt->pkt.user_id->is_primary) {
+ prefs = k->pkt->pkt.user_id->prefs;
+ break;
+ }
+ }
+ for(k=keyblock; k; k = k->next ) {
+ if ( k->pkt->pkttype == PKT_PUBLIC_KEY
+ || k->pkt->pkttype == PKT_PUBLIC_SUBKEY ) {
+ PKT_public_key *pk = k->pkt->pkt.public_key;
+ if (pk->prefs)
+ m_free (pk->prefs);
+ pk->prefs = copy_prefs (prefs);
+ }
+ }
+
}
@@ -1955,9 +2028,8 @@ premerge_public_with_secret ( KBNODE pubblock, KBNODE secblock )
************* Find stuff ***********************
************************************************/
-static int
-find_by_name( KBNODE keyblock, const char *name,
- int mode, byte *namehash )
+static PKT_user_id *
+find_by_name( KBNODE keyblock, const char *name, int mode )
{
KBNODE k;
@@ -1965,23 +2037,11 @@ find_by_name( KBNODE keyblock, const char *name,
if( k->pkt->pkttype == PKT_USER_ID
&& !compare_name( k->pkt->pkt.user_id->name,
k->pkt->pkt.user_id->len, name, mode)) {
- /* we found a matching name, look for the key */
- if( k->pkt->pkt.user_id->photo ) {
- /* oops: this can never happen */
- rmd160_hash_buffer( namehash,
- k->pkt->pkt.user_id->photo,
- k->pkt->pkt.user_id->photolen );
- }
- else {
- rmd160_hash_buffer( namehash,
- k->pkt->pkt.user_id->name,
- k->pkt->pkt.user_id->len );
- }
- return 1;
+ return k->pkt->pkt.user_id;
}
}
- return 0;
+ return NULL;
}
@@ -2068,7 +2128,7 @@ find_by_fpr( KBNODE keyblock, const char *name, int mode )
*/
static int
-finish_lookup( GETKEY_CTX ctx, KBNODE foundk )
+finish_lookup( GETKEY_CTX ctx, KBNODE foundk, PKT_user_id *foundu )
{
KBNODE keyblock = ctx->keyblock;
KBNODE k;
@@ -2098,6 +2158,10 @@ finish_lookup( GETKEY_CTX ctx, KBNODE foundk )
}
if (!req_usage) {
+ PKT_public_key *pk = foundk->pkt->pkt.public_key;
+ if (pk->user_id)
+ free_user_id (pk->user_id);
+ pk->user_id = scopy_user_id (foundu);
ctx->found_key = foundk;
cache_user_id( keyblock );
return 1; /* found */
@@ -2200,6 +2264,13 @@ finish_lookup( GETKEY_CTX ctx, KBNODE foundk )
log_debug( "\tusing key %08lX\n",
(ulong)keyid_from_pk( latest_key->pkt->pkt.public_key, NULL) );
+ if (latest_key) {
+ PKT_public_key *pk = latest_key->pkt->pkt.public_key;
+ if (pk->user_id)
+ free_user_id (pk->user_id);
+ pk->user_id = scopy_user_id (foundu);
+ }
+
ctx->found_key = latest_key;
if (latest_key != keyblock && opt.verbose) {
@@ -2220,8 +2291,6 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode )
{
int rc;
int oldmode = set_packet_list_mode(0);
- byte namehash[20];
- int use_namehash=0;
KBNODE secblock = NULL; /* helper */
int no_suitable_key = 0;
@@ -2261,12 +2330,12 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode )
for(n=0; n < ctx->nitems; n++, item++ ) {
KBNODE k = NULL;
int found = 0;
+ PKT_user_id *found_uid = NULL;
if( item->mode < 10 ) {
- found = find_by_name( ctx->keyblock,
- item->name, item->mode,
- namehash );
- use_namehash = found;
+ found_uid = find_by_name( ctx->keyblock,
+ item->name, item->mode );
+ found = !!found_uid;
}
else if( item->mode >= 10 && item->mode <= 12 ) {
k = find_by_keyid( ctx->keyblock,
@@ -2287,7 +2356,7 @@ lookup( GETKEY_CTX ctx, KBNODE *ret_keyblock, int secmode )
if( found ) {
/* this keyblock looks fine - do further investigation */
merge_selfsigs ( ctx->keyblock );
- if ( finish_lookup( ctx, k ) ) {
+ if ( finish_lookup( ctx, k, found_uid ) ) {
no_suitable_key = 0;
if ( secmode ) {
merge_public_with_secret ( ctx->keyblock,