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