fc5e1fa41ac6d4414bbc2ffa3ffc695b02d70749
[platform/upstream/gpg2.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                          "https://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
269     if( (rc=do_check_messages(pk,sig,r_expired,r_revoked)) )
270         return rc;
271
272     if (sig->digest_algo == GCRY_MD_MD5
273         && !opt.flags.allow_weak_digest_algos)
274       {
275         print_md5_rejected_note ();
276         return GPG_ERR_DIGEST_ALGO;
277       }
278
279     /* Make sure the digest algo is enabled (in case of a detached
280        signature).  */
281     gcry_md_enable (digest, sig->digest_algo);
282
283     /* Complete the digest. */
284     if( sig->version >= 4 )
285         gcry_md_putc( digest, sig->version );
286     gcry_md_putc( digest, sig->sig_class );
287     if( sig->version < 4 ) {
288         u32 a = sig->timestamp;
289         gcry_md_putc( digest, (a >> 24) & 0xff );
290         gcry_md_putc( digest, (a >> 16) & 0xff );
291         gcry_md_putc( digest, (a >>     8) & 0xff );
292         gcry_md_putc( digest,  a           & 0xff );
293     }
294     else {
295         byte buf[6];
296         size_t n;
297         gcry_md_putc( digest, sig->pubkey_algo );
298         gcry_md_putc( digest, sig->digest_algo );
299         if( sig->hashed ) {
300             n = sig->hashed->len;
301             gcry_md_putc (digest, (n >> 8) );
302             gcry_md_putc (digest,  n       );
303             gcry_md_write (digest, sig->hashed->data, n);
304             n += 6;
305         }
306         else {
307           /* Two octets for the (empty) length of the hashed
308              section. */
309           gcry_md_putc (digest, 0);
310           gcry_md_putc (digest, 0);
311           n = 6;
312         }
313         /* add some magic */
314         buf[0] = sig->version;
315         buf[1] = 0xff;
316         buf[2] = n >> 24;
317         buf[3] = n >> 16;
318         buf[4] = n >>  8;
319         buf[5] = n;
320         gcry_md_write( digest, buf, 6 );
321     }
322     gcry_md_final( digest );
323
324     result = encode_md_value( pk, NULL, digest, sig->digest_algo );
325     if (!result)
326         return G10ERR_GENERAL;
327     rc = pk_verify( pk->pubkey_algo, result, sig->data, pk->pkey );
328     gcry_mpi_release (result);
329
330     if( !rc && sig->flags.unknown_critical )
331       {
332         log_info(_("assuming bad signature from key %s"
333                    " due to an unknown critical bit\n"),keystr_from_pk(pk));
334         rc = G10ERR_BAD_SIGN;
335       }
336
337     if(!rc && ret_pk)
338       copy_public_key(ret_pk,pk);
339
340     return rc;
341 }
342
343
344
345 static void
346 hash_uid_node( KBNODE unode, gcry_md_hd_t md, PKT_signature *sig )
347 {
348     PKT_user_id *uid = unode->pkt->pkt.user_id;
349
350     assert( unode->pkt->pkttype == PKT_USER_ID );
351     if( uid->attrib_data ) {
352         if( sig->version >=4 ) {
353             byte buf[5];
354             buf[0] = 0xd1;                   /* packet of type 17 */
355             buf[1] = uid->attrib_len >> 24;  /* always use 4 length bytes */
356             buf[2] = uid->attrib_len >> 16;
357             buf[3] = uid->attrib_len >>  8;
358             buf[4] = uid->attrib_len;
359             gcry_md_write( md, buf, 5 );
360         }
361         gcry_md_write( md, uid->attrib_data, uid->attrib_len );
362     }
363     else {
364         if( sig->version >=4 ) {
365             byte buf[5];
366             buf[0] = 0xb4;            /* indicates a userid packet */
367             buf[1] = uid->len >> 24;  /* always use 4 length bytes */
368             buf[2] = uid->len >> 16;
369             buf[3] = uid->len >>  8;
370             buf[4] = uid->len;
371             gcry_md_write( md, buf, 5 );
372         }
373         gcry_md_write( md, uid->name, uid->len );
374     }
375 }
376
377 static void
378 cache_sig_result ( PKT_signature *sig, int result )
379 {
380     if ( !result ) {
381         sig->flags.checked = 1;
382         sig->flags.valid = 1;
383     }
384     else if ( gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE ) {
385         sig->flags.checked = 1;
386         sig->flags.valid = 0;
387     }
388     else {
389         sig->flags.checked = 0;
390         sig->flags.valid = 0;
391     }
392 }
393
394 /* Check the revocation keys to see if any of them have revoked our
395    pk.  sig is the revocation sig.  pk is the key it is on.  This code
396    will need to be modified if gpg ever becomes multi-threaded.  Note
397    that this guarantees that a designated revocation sig will never be
398    considered valid unless it is actually valid, as well as being
399    issued by a revocation key in a valid direct signature.  Note also
400    that this is written so that a revoked revoker can still issue
401    revocations: i.e. If A revokes B, but A is revoked, B is still
402    revoked.  I'm not completely convinced this is the proper behavior,
403    but it matches how PGP does it. -dms */
404
405 /* Returns 0 if sig is valid (i.e. pk is revoked), non-0 if not
406    revoked.  It is important that G10ERR_NO_PUBKEY is only returned
407    when a revocation signature is from a valid revocation key
408    designated in a revkey subpacket, but the revocation key itself
409    isn't present. */
410 int
411 check_revocation_keys(PKT_public_key *pk,PKT_signature *sig)
412 {
413   static int busy=0;
414   int i,rc=G10ERR_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
425       pk->dont_cache=1;
426       return rc;
427     }
428
429   busy=1;
430
431   /*  printf("looking at %08lX with a sig from %08lX\n",(ulong)pk->keyid[1],
432       (ulong)sig->keyid[1]); */
433
434   /* is the issuer of the sig one of our revokers? */
435   if( !pk->revkey && pk->numrevkeys )
436      BUG();
437   else
438       for(i=0;i<pk->numrevkeys;i++)
439         {
440           u32 keyid[2];
441
442           keyid_from_fingerprint(pk->revkey[i].fpr,MAX_FINGERPRINT_LEN,keyid);
443
444           if(keyid[0]==sig->keyid[0] && keyid[1]==sig->keyid[1])
445             {
446               gcry_md_hd_t md;
447
448               if (gcry_md_open (&md, sig->digest_algo, 0))
449                 BUG ();
450               hash_public_key(md,pk);
451               rc=signature_check(sig,md);
452               cache_sig_result(sig,rc);
453               gcry_md_close (md);
454               break;
455             }
456         }
457
458   busy=0;
459
460   return rc;
461 }
462
463 /* Backsigs (0x19) have the same format as binding sigs (0x18), but
464    this function is simpler than check_key_signature in a few ways.
465    For example, there is no support for expiring backsigs since it is
466    questionable what such a thing actually means.  Note also that the
467    sig cache check here, unlike other sig caches in GnuPG, is not
468    persistent. */
469 int
470 check_backsig(PKT_public_key *main_pk,PKT_public_key *sub_pk,
471               PKT_signature *backsig)
472 {
473   gcry_md_hd_t md;
474   int rc;
475
476   /* Always check whether the algorithm is available.  Although
477      gcry_md_open woyuld throw an error, some libgcrypt versions will
478      print a debug message in that case too. */
479   if ((rc=openpgp_md_test_algo (backsig->digest_algo)))
480     return rc;
481
482   if(!opt.no_sig_cache && backsig->flags.checked)
483     return backsig->flags.valid? 0 : gpg_error (GPG_ERR_BAD_SIGNATURE);
484
485   rc = gcry_md_open (&md, backsig->digest_algo,0);
486   if (!rc)
487     {
488       hash_public_key(md,main_pk);
489       hash_public_key(md,sub_pk);
490       rc=do_check(sub_pk,backsig,md,NULL,NULL,NULL);
491       cache_sig_result(backsig,rc);
492       gcry_md_close(md);
493     }
494
495   return rc;
496 }
497
498
499 /****************
500  * check the signature pointed to by NODE. This is a key signature.
501  * If the function detects a self-signature, it uses the PK from
502  * ROOT and does not read any public key.
503  */
504 int
505 check_key_signature( KBNODE root, KBNODE node, int *is_selfsig )
506 {
507   return check_key_signature2(root, node, NULL, NULL, is_selfsig, NULL, NULL );
508 }
509
510 /* If check_pk is set, then use it to check the signature in node
511    rather than getting it from root or the keydb.  If ret_pk is set,
512    fill in the public key that was used to verify the signature.
513    ret_pk is only meaningful when the verification was successful. */
514 /* TODO: add r_revoked here as well.  It has the same problems as
515    r_expiredate and r_expired and the cache. */
516 int
517 check_key_signature2( KBNODE root, KBNODE node, PKT_public_key *check_pk,
518                       PKT_public_key *ret_pk, int *is_selfsig,
519                       u32 *r_expiredate, int *r_expired )
520 {
521     gcry_md_hd_t md;
522     PKT_public_key *pk;
523     PKT_signature *sig;
524     int algo;
525     int rc;
526
527     if( is_selfsig )
528         *is_selfsig = 0;
529     if( r_expiredate )
530         *r_expiredate = 0;
531     if( r_expired )
532         *r_expired = 0;
533     assert( node->pkt->pkttype == PKT_SIGNATURE );
534     assert( root->pkt->pkttype == PKT_PUBLIC_KEY );
535
536     pk = root->pkt->pkt.public_key;
537     sig = node->pkt->pkt.signature;
538     algo = sig->digest_algo;
539
540     /* Check whether we have cached the result of a previous signature
541        check.  Note that we may no longer have the pubkey or hash
542        needed to verify a sig, but can still use the cached value.  A
543        cache refresh detects and clears these cases.
544        For safety reasons we ignore cache entries from MD5 signatures.  */
545     if ( !opt.no_sig_cache ) {
546         if (sig->flags.checked && sig->digest_algo != DIGEST_ALGO_MD5) {
547             /*cached status available*/
548             if( is_selfsig ) {
549                 u32 keyid[2];
550
551                 keyid_from_pk( pk, keyid );
552                 if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
553                     *is_selfsig = 1;
554             }
555             /* BUG: This is wrong for non-self-sigs.. needs to be the
556                actual pk */
557             if((rc=do_check_messages(pk,sig,r_expired,NULL)))
558               return rc;
559             return sig->flags.valid? 0 : gpg_error (GPG_ERR_BAD_SIGNATURE);
560         }
561     }
562
563     if( (rc=openpgp_pk_test_algo(sig->pubkey_algo)) )
564         return rc;
565     if( (rc=openpgp_md_test_algo(algo)) )
566         return rc;
567
568     if( sig->sig_class == 0x20 ) { /* key revocation */
569         u32 keyid[2];
570         keyid_from_pk( pk, keyid );
571
572         /* is it a designated revoker? */
573         if(keyid[0]!=sig->keyid[0] || keyid[1]!=sig->keyid[1])
574           rc=check_revocation_keys(pk,sig);
575         else
576           {
577             if (gcry_md_open (&md, algo, 0 ))
578               BUG ();
579             hash_public_key( md, pk );
580             rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
581             cache_sig_result ( sig, rc );
582             gcry_md_close(md);
583           }
584     }
585     else if( sig->sig_class == 0x28 ) { /* subkey revocation */
586         KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY );
587
588         if( snode ) {
589             if (gcry_md_open (&md, algo, 0))
590               BUG ();
591             hash_public_key( md, pk );
592             hash_public_key( md, snode->pkt->pkt.public_key );
593             rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
594             cache_sig_result ( sig, rc );
595             gcry_md_close(md);
596         }
597         else
598           {
599             if (opt.verbose)
600               log_info (_("key %s: no subkey for subkey"
601                           " revocation signature\n"),keystr_from_pk(pk));
602             rc = G10ERR_SIG_CLASS;
603           }
604     }
605     else if( sig->sig_class == 0x18 ) { /* key binding */
606         KBNODE snode = find_prev_kbnode( root, node, PKT_PUBLIC_SUBKEY );
607
608         if( snode ) {
609             if( is_selfsig ) {  /* does this make sense????? */
610                 u32 keyid[2];   /* it should always be a selfsig */
611
612                 keyid_from_pk( pk, keyid );
613                 if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
614                     *is_selfsig = 1;
615             }
616             if (gcry_md_open (&md, algo, 0))
617               BUG ();
618             hash_public_key( md, pk );
619             hash_public_key( md, snode->pkt->pkt.public_key );
620             rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
621             cache_sig_result ( sig, rc );
622             gcry_md_close(md);
623         }
624         else
625           {
626             if (opt.verbose)
627               log_info(_("key %s: no subkey for subkey"
628                          " binding signature\n"),keystr_from_pk(pk));
629             rc = G10ERR_SIG_CLASS;
630           }
631     }
632     else if( sig->sig_class == 0x1f ) { /* direct key signature */
633         if (gcry_md_open (&md, algo, 0 ))
634           BUG ();
635         hash_public_key( md, pk );
636         rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
637         cache_sig_result ( sig, rc );
638         gcry_md_close(md);
639     }
640     else { /* all other classes */
641         KBNODE unode = find_prev_kbnode( root, node, PKT_USER_ID );
642
643         if( unode ) {
644             u32 keyid[2];
645
646             keyid_from_pk( pk, keyid );
647             if (gcry_md_open (&md, algo, 0 ))
648               BUG ();
649             hash_public_key( md, pk );
650             hash_uid_node( unode, md, sig );
651             if( keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1] )
652               {
653                 if( is_selfsig )
654                   *is_selfsig = 1;
655                 rc = do_check( pk, sig, md, r_expired, NULL, ret_pk );
656               }
657             else if (check_pk)
658               rc=do_check(check_pk,sig,md,r_expired,NULL,ret_pk);
659             else
660               rc=signature_check2(sig,md,r_expiredate,r_expired,NULL,ret_pk);
661
662             cache_sig_result ( sig, rc );
663             gcry_md_close(md);
664         }
665         else
666           {
667             if (!opt.quiet)
668               log_info ("key %s: no user ID for key signature packet"
669                         " of class %02x\n",keystr_from_pk(pk),sig->sig_class);
670             rc = G10ERR_SIG_CLASS;
671           }
672     }
673
674     return rc;
675 }