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