2009-09-23 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / g10 / sig-check.c
1 /* sig-check.c -  Check a signature
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
3  *               2004, 2006 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26
27 #include "gpg.h"
28 #include "util.h"
29 #include "packet.h"
30 #include "keydb.h"
31 #include "cipher.h"
32 #include "main.h"
33 #include "status.h"
34 #include "i18n.h"
35 #include "options.h"
36 #include "pkglue.h"
37
38 /* Context used by the compare function. */
39 struct cmp_help_context_s
40 {
41   PKT_signature *sig;
42   gcry_md_hd_t md;
43 };
44
45
46
47 static int do_check( PKT_public_key *pk, PKT_signature *sig,
48                      gcry_md_hd_t digest,
49                      int *r_expired, int *r_revoked, PKT_public_key *ret_pk);
50
51 /****************
52  * Check the signature which is contained in SIG.
53  * The MD_HANDLE should be currently open, so that this function
54  * is able to append some data, before finalizing the digest.
55  */
56 int
57 signature_check (PKT_signature *sig, gcry_md_hd_t digest)
58 {
59     return signature_check2( sig, digest, NULL, NULL, NULL, NULL );
60 }
61
62 int
63 signature_check2 (PKT_signature *sig, gcry_md_hd_t digest, u32 *r_expiredate, 
64                   int *r_expired, int *r_revoked, PKT_public_key *ret_pk )
65 {
66     PKT_public_key *pk = xmalloc_clear( sizeof *pk );
67     int rc=0;
68
69     if ( (rc=openpgp_md_test_algo(sig->digest_algo)) )
70       ; /* We don't have this digest. */
71     else if ((rc=openpgp_pk_test_algo(sig->pubkey_algo)))
72       ; /* We don't have this pubkey algo. */
73     else if (!gcry_md_is_enabled (digest,sig->digest_algo))
74       {
75         /* Sanity check that the md has a context for the hash that the
76            sig is expecting.  This can happen if a onepass sig header does
77            not match the actual sig, and also if the clearsign "Hash:"
78            header is missing or does not match the actual sig. */
79
80         log_info(_("WARNING: signature digest conflict in message\n"));
81         rc=G10ERR_GENERAL;
82       }
83     else if( get_pubkey( pk, sig->keyid ) )
84         rc = G10ERR_NO_PUBKEY;
85     else if(!pk->is_valid && !pk->is_primary)
86         rc=G10ERR_BAD_PUBKEY; /* you cannot have a good sig from an
87                                  invalid subkey */
88     else
89       {
90         if(r_expiredate)
91           *r_expiredate = pk->expiredate;
92
93         rc = do_check( pk, sig, digest, r_expired, r_revoked, ret_pk );
94
95         /* Check the backsig.  This is a 0x19 signature from the
96            subkey on the primary key.  The idea here is that it should
97            not be possible for someone to "steal" subkeys and claim
98            them as their own.  The attacker couldn't actually use the
99            subkey, but they could try and claim ownership of any
100            signaures issued by it. */
101         if(rc==0 && !pk->is_primary && pk->backsig<2)
102           {
103             if(pk->backsig==0)
104               {
105                 log_info(_("WARNING: signing subkey %s is not"
106                            " cross-certified\n"),keystr_from_pk(pk));
107                 log_info(_("please see %s for more information\n"),
108                          "http://www.gnupg.org/faq/subkey-cross-certify.html");
109                 /* --require-cross-certification makes this warning an
110                      error.  TODO: change the default to require this
111                      after more keys have backsigs. */
112                 if(opt.flags.require_cross_cert)
113                   rc=G10ERR_GENERAL;
114               }
115             else if(pk->backsig==1)
116               {
117                 log_info(_("WARNING: signing subkey %s has an invalid"
118                            " cross-certification\n"),keystr_from_pk(pk));
119                 rc=G10ERR_GENERAL;
120               }
121           }
122       }
123
124     free_public_key( pk );
125
126     if( !rc && sig->sig_class < 2 && is_status_enabled() ) {
127         /* This signature id works best with DLP algorithms because
128          * they use a random parameter for every signature.  Instead of
129          * this sig-id we could have also used the hash of the document
130          * and the timestamp, but the drawback of this is, that it is
131          * not possible to sign more than one identical document within
132          * one second.  Some remote batch processing applications might
133          * like this feature here.  
134          * 
135          * Note that before 2.0.10, we used RIPE-MD160 for the hash
136          * and accidently didn't include the timestamp and algorithm
137          * information in the hash.  Given that this feature is not
138          * commonly used and that a replay attacks detection should
139          * not solely be based on this feature (because it does not
140          * work with RSA), we take the freedom and switch to SHA-1
141          * with 2.0.10 to take advantage of hardware supported SHA-1
142          * implementations.  We also include the missing information
143          * in the hash.  Note also the SIG_ID as computed by gpg 1.x
144          * and gpg 2.x didn't matched either because 2.x used to print
145          * MPIs not in PGP format.  */
146         u32 a = sig->timestamp;
147         int nsig = pubkey_get_nsig( sig->pubkey_algo );
148         unsigned char *p, *buffer;
149         size_t n, nbytes;
150         int i;
151         char hashbuf[20];
152
153         nbytes = 6;
154         for (i=0; i < nsig; i++ )
155           {
156             if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &n, sig->data[i]))
157               BUG();
158             nbytes += n;
159           }
160
161         /* Make buffer large enough to be later used as output buffer.  */
162         if (nbytes < 100)
163           nbytes = 100;
164         nbytes += 10;  /* Safety margin.  */
165
166         /* Fill and hash buffer.  */
167         buffer = p = xmalloc (nbytes);
168         *p++ = sig->pubkey_algo;
169         *p++ = sig->digest_algo;
170         *p++ = (a >> 24) & 0xff;
171         *p++ = (a >> 16) & 0xff;
172         *p++ = (a >>  8) & 0xff;
173         *p++ =  a & 0xff;
174         nbytes -= 6;
175         for (i=0; i < nsig; i++ )
176           {
177             if (gcry_mpi_print (GCRYMPI_FMT_PGP, p, nbytes, &n, sig->data[i]))
178               BUG();
179             p += n;
180             nbytes -= n;
181           }
182         gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf, buffer, p-buffer);
183
184         p = make_radix64_string (hashbuf, 20);
185         sprintf (buffer, "%s %s %lu",
186                  p, strtimestamp (sig->timestamp), (ulong)sig->timestamp);
187         xfree (p);
188         write_status_text (STATUS_SIG_ID, buffer);
189         xfree (buffer);
190     }
191
192     return rc;
193 }
194
195
196 static int
197 do_check_messages( PKT_public_key *pk, PKT_signature *sig,
198                    int *r_expired, int *r_revoked )
199 {
200     u32 cur_time;
201
202     if(r_expired)
203       *r_expired = 0;
204     if(r_revoked)
205       *r_revoked = 0;
206
207     if( pk->timestamp > sig->timestamp )
208       {
209         ulong d = pk->timestamp - sig->timestamp;
210         log_info(d==1
211                  ?_("public key %s is %lu second newer than the signature\n")
212                  :_("public key %s is %lu seconds newer than the signature\n"),
213                  keystr_from_pk(pk),d );
214         if( !opt.ignore_time_conflict )
215           return G10ERR_TIME_CONFLICT; /* pubkey newer than signature */
216       }
217
218     cur_time = make_timestamp();
219     if( pk->timestamp > cur_time )
220       {
221         ulong d = pk->timestamp - cur_time;
222         log_info( d==1
223                   ? _("key %s was created %lu second"
224                       " in the future (time warp or clock problem)\n")
225                   : _("key %s was created %lu seconds"
226                       " in the future (time warp or clock problem)\n"),
227                   keystr_from_pk(pk),d );
228         if( !opt.ignore_time_conflict )
229           return G10ERR_TIME_CONFLICT;
230       }
231
232     /* Check whether the key has expired.  We check the has_expired
233        flag which is set after a full evaluation of the key (getkey.c)
234        as well as a simple compare to the current time in case the
235        merge has for whatever reasons not been done.  */
236     if( pk->has_expired || (pk->expiredate && pk->expiredate < cur_time)) {
237         char buf[11];
238         if (opt.verbose)
239           log_info(_("NOTE: signature key %s expired %s\n"),
240                    keystr_from_pk(pk), asctimestamp( pk->expiredate ) );
241         /* SIGEXPIRED is deprecated.  Use KEYEXPIRED. */
242         snprintf (buf, sizeof buf,"%lu",(ulong)pk->expiredate);
243         write_status_text(STATUS_KEYEXPIRED,buf);
244         write_status(STATUS_SIGEXPIRED);
245         if(r_expired)
246           *r_expired = 1;
247     }
248
249     if (pk->is_revoked)
250       {
251         if (opt.verbose)
252           log_info (_("NOTE: signature key %s has been revoked\n"),
253                     keystr_from_pk(pk));
254         if (r_revoked)
255           *r_revoked=1;
256       }
257
258     return 0;
259 }
260
261
262 static int
263 do_check( PKT_public_key *pk, PKT_signature *sig, gcry_md_hd_t digest,
264           int *r_expired, int *r_revoked, PKT_public_key *ret_pk )
265 {
266     gcry_mpi_t result = NULL;
267     int rc = 0;
268     struct cmp_help_context_s ctx;
269
270     if( (rc=do_check_messages(pk,sig,r_expired,r_revoked)) )
271         return rc;
272
273     /* Make sure the digest algo is enabled (in case of a detached
274        signature).  */
275     gcry_md_enable (digest, sig->digest_algo);
276
277     /* Complete the digest. */
278     if( sig->version >= 4 )
279         gcry_md_putc( digest, sig->version );
280     gcry_md_putc( digest, sig->sig_class );
281     if( sig->version < 4 ) {
282         u32 a = sig->timestamp;
283         gcry_md_putc( digest, (a >> 24) & 0xff );
284         gcry_md_putc( digest, (a >> 16) & 0xff );
285         gcry_md_putc( digest, (a >>     8) & 0xff );
286         gcry_md_putc( digest,  a           & 0xff );
287     }
288     else {
289         byte buf[6];
290         size_t n;
291         gcry_md_putc( digest, sig->pubkey_algo );
292         gcry_md_putc( digest, sig->digest_algo );
293         if( sig->hashed ) {
294             n = sig->hashed->len;
295             gcry_md_putc (digest, (n >> 8) );
296             gcry_md_putc (digest,  n       );
297             gcry_md_write (digest, sig->hashed->data, n);
298             n += 6;
299         }
300         else {
301           /* Two octets for the (empty) length of the hashed
302              section. */
303           gcry_md_putc (digest, 0);
304           gcry_md_putc (digest, 0);
305           n = 6;
306         }
307         /* add some magic */
308         buf[0] = sig->version;
309         buf[1] = 0xff;
310         buf[2] = n >> 24;
311         buf[3] = n >> 16;
312         buf[4] = n >>  8;
313         buf[5] = n;
314         gcry_md_write( digest, buf, 6 );
315     }
316     gcry_md_final( digest );
317
318     result = encode_md_value( pk, NULL, digest, sig->digest_algo );
319     if (!result)
320         return G10ERR_GENERAL;
321     ctx.sig = sig;
322     ctx.md = digest;
323     rc = pk_verify( pk->pubkey_algo, result, sig->data, pk->pkey );
324     gcry_mpi_release (result);
325
326     if( !rc && sig->flags.unknown_critical )
327       {
328         log_info(_("assuming bad signature from key %s"
329                    " due to an unknown critical bit\n"),keystr_from_pk(pk));
330         rc = G10ERR_BAD_SIGN;
331       }
332
333     if(!rc && ret_pk)
334       copy_public_key(ret_pk,pk);
335
336     return rc;
337 }
338
339
340
341 static void
342 hash_uid_node( KBNODE unode, gcry_md_hd_t md, PKT_signature *sig )
343 {
344     PKT_user_id *uid = unode->pkt->pkt.user_id;
345
346     assert( unode->pkt->pkttype == PKT_USER_ID );
347     if( uid->attrib_data ) {
348         if( sig->version >=4 ) {
349             byte buf[5];
350             buf[0] = 0xd1;                   /* packet of type 17 */
351             buf[1] = uid->attrib_len >> 24;  /* always use 4 length bytes */
352             buf[2] = uid->attrib_len >> 16;
353             buf[3] = uid->attrib_len >>  8;
354             buf[4] = uid->attrib_len;
355             gcry_md_write( md, buf, 5 );
356         }
357         gcry_md_write( md, uid->attrib_data, uid->attrib_len );
358     }
359     else {
360         if( sig->version >=4 ) {
361             byte buf[5];
362             buf[0] = 0xb4;            /* indicates a userid packet */
363             buf[1] = uid->len >> 24;  /* always use 4 length bytes */
364             buf[2] = uid->len >> 16;
365             buf[3] = uid->len >>  8;
366             buf[4] = uid->len;
367             gcry_md_write( md, buf, 5 );
368         }
369         gcry_md_write( md, uid->name, uid->len );
370     }
371 }
372
373 static void
374 cache_sig_result ( PKT_signature *sig, int result )
375 {
376     if ( !result ) {
377         sig->flags.checked = 1;
378         sig->flags.valid = 1;
379     }
380     else if ( gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE ) {
381         sig->flags.checked = 1;
382         sig->flags.valid = 0;
383     }
384     else {
385         sig->flags.checked = 0;
386         sig->flags.valid = 0;
387     }
388 }
389
390 /* Check the revocation keys to see if any of them have revoked our
391    pk.  sig is the revocation sig.  pk is the key it is on.  This code
392    will need to be modified if gpg ever becomes multi-threaded.  Note
393    that this guarantees that a designated revocation sig will never be
394    considered valid unless it is actually valid, as well as being
395    issued by a revocation key in a valid direct signature.  Note also
396    that this is written so that a revoked revoker can still issue
397    revocations: i.e. If A revokes B, but A is revoked, B is still
398    revoked.  I'm not completely convinced this is the proper behavior,
399    but it matches how PGP does it. -dms */
400
401 /* Returns 0 if sig is valid (i.e. pk is revoked), non-0 if not
402    revoked.  It is important that G10ERR_NO_PUBKEY is only returned
403    when a revocation signature is from a valid revocation key
404    designated in a revkey subpacket, but the revocation key itself
405    isn't present. */
406 int
407 check_revocation_keys(PKT_public_key *pk,PKT_signature *sig)
408 {
409   static int busy=0;
410   int i,rc=G10ERR_GENERAL;
411
412   assert(IS_KEY_REV(sig));
413   assert((sig->keyid[0]!=pk->keyid[0]) || (sig->keyid[0]!=pk->keyid[1]));
414
415   if(busy)
416     {
417       /* return an error (i.e. not revoked), but mark the pk as
418          uncacheable as we don't really know its revocation status
419          until it is checked directly. */
420
421       pk->dont_cache=1;
422       return rc;
423     }
424
425   busy=1;
426
427   /*  printf("looking at %08lX with a sig from %08lX\n",(ulong)pk->keyid[1],
428       (ulong)sig->keyid[1]); */
429
430   /* is the issuer of the sig one of our revokers? */
431   if( !pk->revkey && pk->numrevkeys )
432      BUG();
433   else
434       for(i=0;i<pk->numrevkeys;i++)
435         {
436           u32 keyid[2];
437     
438           keyid_from_fingerprint(pk->revkey[i].fpr,MAX_FINGERPRINT_LEN,keyid);
439     
440           if(keyid[0]==sig->keyid[0] && keyid[1]==sig->keyid[1])
441             {
442               gcry_md_hd_t md;
443     
444               if (gcry_md_open (&md, sig->digest_algo, 0))
445                 BUG ();
446               hash_public_key(md,pk);
447               rc=signature_check(sig,md);
448               cache_sig_result(sig,rc);
449               gcry_md_close (md);
450               break;
451             }
452         }
453
454   busy=0;
455
456   return rc;
457
458
459 /* Backsigs (0x19) have the same format as binding sigs (0x18), but
460    this function is simpler than check_key_signature in a few ways.
461    For example, there is no support for expiring backsigs since it is
462    questionable what such a thing actually means.  Note also that the
463    sig cache check here, unlike other sig caches in GnuPG, is not
464    persistent. */
465 int
466 check_backsig(PKT_public_key *main_pk,PKT_public_key *sub_pk,
467               PKT_signature *backsig)
468 {
469   gcry_md_hd_t md;
470   int rc;
471
472   /* Always check whether the algorithm is available.  Although
473      gcry_md_open woyuld throw an error, some libgcrypt versions will
474      print a debug message in that case too. */
475   if ((rc=openpgp_md_test_algo (backsig->digest_algo)))
476     return rc;
477
478   if(!opt.no_sig_cache && backsig->flags.checked)
479     return backsig->flags.valid? 0 : gpg_error (GPG_ERR_BAD_SIGNATURE);
480
481   rc = gcry_md_open (&md, backsig->digest_algo,0);
482   if (!rc)
483     {
484       hash_public_key(md,main_pk);
485       hash_public_key(md,sub_pk);
486       rc=do_check(sub_pk,backsig,md,NULL,NULL,NULL);
487       cache_sig_result(backsig,rc);
488       gcry_md_close(md);
489     }
490
491   return rc;
492 }
493
494
495 /****************
496  * check the signature pointed to by NODE. This is a key signature.
497  * If the function detects a self-signature, it uses the PK from
498  * ROOT and does not read any public key.
499  */
500 int
501 check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
502 {
503   return check_key_signature2(root, node, NULL, NULL, is_selfsig, NULL, NULL );
504 }
505
506 /* If check_pk is set, then use it to check the signature in node
507    rather than getting it from root or the keydb.  If ret_pk is set,
508    fill in the public key that was used to verify the signature.
509    ret_pk is only meaningful when the verification was successful. */
510 /* TODO: add r_revoked here as well.  It has the same problems as
511    r_expiredate and r_expired and the cache. */
512 int
513 check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
514                       PKT_public_key *ret_pk, int *is_selfsig,
515                       u32 *r_expiredate, int *r_expired )
516 {
517     gcry_md_hd_t md;
518     PKT_public_key *pk;
519     PKT_signature *sig;
520     int algo;
521     int rc;
522
523     if( is_selfsig )
524         *is_selfsig = 0;
525     if( r_expiredate )
526         *r_expiredate = 0;
527     if( r_expired )
528         *r_expired = 0;
529     assert( node->pkt->pkttype == PKT_SIGNATURE );
530     assert( root->pkt->pkttype == PKT_PUBLIC_KEY );
531
532     pk = root->pkt->pkt.public_key;
533     sig = node->pkt->pkt.signature;
534     algo = sig->digest_algo;
535
536     /* Check whether we have cached the result of a previous signature
537        check.  Note that we may no longer have the pubkey or hash
538        needed to verify a sig, but can still use the cached value.  A
539        cache refresh detects and clears these cases. */
540     if ( !opt.no_sig_cache ) {
541         if (sig->flags.checked) { /*cached status available*/
542             if( is_selfsig ) {  
543                 u32 keyid[2];   
544
545                 keyid_from_pk( pk, keyid );
546                 if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
547                     *is_selfsig = 1;
548             }
549             /* BUG: This is wrong for non-self-sigs.. needs to be the
550                actual pk */
551             if((rc=do_check_messages(pk,sig,r_expired,NULL)))
552               return rc;
553             return sig->flags.valid? 0 : gpg_error (GPG_ERR_BAD_SIGNATURE);
554         }
555     }
556
557     if( (rc=openpgp_pk_test_algo(sig->pubkey_algo)) )
558         return rc;
559     if( (rc=openpgp_md_test_algo(algo)) )
560         return rc;
561
562     if( sig->sig_class == 0x20 ) { /* key revocation */
563         u32 keyid[2];   
564         keyid_from_pk( pk, keyid );
565
566         /* is it a designated revoker? */
567         if(keyid[0]!=sig->keyid[0] || keyid[1]!=sig->keyid[1])
568           rc=check_revocation_keys(pk,sig);
569         else
570           {
571             if (gcry_md_open (&md, algo, 0 ))
572               BUG ();
573             hash_public_key( md, pk );
574             rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
575             cache_sig_result ( sig, rc );
576             gcry_md_close(md);
577           }
578     }
579     else if( sig->sig_class == 0x28 ) { /* subkey revocation */
580         KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY );
581
582         if( snode ) {
583             if (gcry_md_open (&md, algo, 0))
584               BUG ();
585             hash_public_key( md, pk );
586             hash_public_key( md, snode->pkt->pkt.public_key );
587             rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
588             cache_sig_result ( sig, rc );
589             gcry_md_close(md);
590         }
591         else
592           {
593             if (opt.verbose)
594               log_info (_("key %s: no subkey for subkey"
595                           " revocation signature\n"),keystr_from_pk(pk));
596             rc = G10ERR_SIG_CLASS;
597           }
598     }
599     else if( sig->sig_class == 0x18 ) { /* key binding */
600         KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY );
601
602         if( snode ) {
603             if( is_selfsig ) {  /* does this make sense????? */
604                 u32 keyid[2];   /* it should always be a selfsig */
605
606                 keyid_from_pk( pk, keyid );
607                 if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
608                     *is_selfsig = 1;
609             }
610             if (gcry_md_open (&md, algo, 0))
611               BUG ();
612             hash_public_key( md, pk );
613             hash_public_key( md, snode->pkt->pkt.public_key );
614             rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
615             cache_sig_result ( sig, rc );
616             gcry_md_close(md);
617         }
618         else
619           {
620             if (opt.verbose)
621               log_info(_("key %s: no subkey for subkey"
622                          " binding signature\n"),keystr_from_pk(pk));
623             rc = G10ERR_SIG_CLASS;
624           }
625     }
626     else if( sig->sig_class == 0x1f ) { /* direct key signature */
627         if (gcry_md_open (&md, algo, 0 ))
628           BUG ();
629         hash_public_key( md, pk );
630         rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
631         cache_sig_result ( sig, rc );
632         gcry_md_close(md);
633     }
634     else { /* all other classes */
635         KBNODE unode = find_prev_kbnode( root, node, PKT_USER_ID );
636
637         if( unode ) {
638             u32 keyid[2];
639
640             keyid_from_pk( pk, keyid );
641             if (gcry_md_open (&md, algo, 0 ))
642               BUG ();
643             hash_public_key( md, pk );
644             hash_uid_node( unode, md, sig );
645             if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
646               {
647                 if( is_selfsig )
648                   *is_selfsig = 1;
649                 rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
650               }
651             else if (check_pk)
652               rc=do_check(check_pk,sig,md,r_expired,NULL,ret_pk);
653             else
654               rc=signature_check2(sig,md,r_expiredate,r_expired,NULL,ret_pk);
655
656             cache_sig_result ( sig, rc );
657             gcry_md_close(md);
658         }
659         else
660           {
661             if (!opt.quiet)
662               log_info ("key %s: no user ID for key signature packet"
663                         " of class %02x\n",keystr_from_pk(pk),sig->sig_class);
664             rc = G10ERR_SIG_CLASS;
665           }
666     }
667
668     return rc;
669 }