g10: Remove unused struct cmp_help_context_s.
[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
38
39
40 static int do_check( PKT_public_key *pk, PKT_signature *sig,
41                      gcry_md_hd_t digest,
42                      int *r_expired, int *r_revoked, PKT_public_key *ret_pk);
43
44 /****************
45  * Check the signature which is contained in SIG.
46  * The MD_HANDLE should be currently open, so that this function
47  * is able to append some data, before finalizing the digest.
48  */
49 int
50 signature_check (PKT_signature *sig, gcry_md_hd_t digest)
51 {
52     return signature_check2( sig, digest, NULL, NULL, NULL, NULL );
53 }
54
55 int
56 signature_check2 (PKT_signature *sig, gcry_md_hd_t digest, u32 *r_expiredate,
57                   int *r_expired, int *r_revoked, PKT_public_key *pk )
58 {
59     int rc=0;
60     int pk_internal;
61
62     if (pk)
63       pk_internal = 0;
64     else
65       {
66         pk_internal = 1;
67         pk = xmalloc_clear( sizeof *pk );
68       }
69
70     if ( (rc=openpgp_md_test_algo(sig->digest_algo)) )
71       ; /* We don't have this digest. */
72     else if ((rc=openpgp_pk_test_algo(sig->pubkey_algo)))
73       ; /* We don't have this pubkey algo. */
74     else if (!gcry_md_is_enabled (digest,sig->digest_algo))
75       {
76         /* Sanity check that the md has a context for the hash that the
77            sig is expecting.  This can happen if a onepass sig header does
78            not match the actual sig, and also if the clearsign "Hash:"
79            header is missing or does not match the actual sig. */
80
81         log_info(_("WARNING: signature digest conflict in message\n"));
82         rc = GPG_ERR_GENERAL;
83       }
84     else if( get_pubkey( pk, sig->keyid ) )
85         rc = GPG_ERR_NO_PUBKEY;
86     else if(!pk->flags.valid && !pk->flags.primary)
87       {
88         /* You cannot have a good sig from an invalid subkey.  */
89         rc = GPG_ERR_BAD_PUBKEY;
90       }
91     else
92       {
93         if(r_expiredate)
94           *r_expiredate = pk->expiredate;
95
96         rc = do_check( pk, sig, digest, r_expired, r_revoked, NULL );
97
98         /* Check the backsig.  This is a 0x19 signature from the
99            subkey on the primary key.  The idea here is that it should
100            not be possible for someone to "steal" subkeys and claim
101            them as their own.  The attacker couldn't actually use the
102            subkey, but they could try and claim ownership of any
103            signaures issued by it. */
104         if(rc==0 && !pk->flags.primary && pk->flags.backsig < 2)
105           {
106             if (!pk->flags.backsig)
107               {
108                 log_info(_("WARNING: signing subkey %s is not"
109                            " cross-certified\n"),keystr_from_pk(pk));
110                 log_info(_("please see %s for more information\n"),
111                          "https://gnupg.org/faq/subkey-cross-certify.html");
112                 /* --require-cross-certification makes this warning an
113                      error.  TODO: change the default to require this
114                      after more keys have backsigs. */
115                 if(opt.flags.require_cross_cert)
116                   rc = GPG_ERR_GENERAL;
117               }
118             else if(pk->flags.backsig == 1)
119               {
120                 log_info(_("WARNING: signing subkey %s has an invalid"
121                            " cross-certification\n"),keystr_from_pk(pk));
122                 rc = GPG_ERR_GENERAL;
123               }
124           }
125       }
126
127     if (pk_internal || rc)
128       {
129         release_public_key_parts (pk);
130         if (pk_internal)
131           xfree (pk);
132         else
133           /* Be very sure that the caller doesn't try to use *PK.  */
134           memset (pk, 0, sizeof (*pk));
135       }
136
137     if( !rc && sig->sig_class < 2 && is_status_enabled() ) {
138         /* This signature id works best with DLP algorithms because
139          * they use a random parameter for every signature.  Instead of
140          * this sig-id we could have also used the hash of the document
141          * and the timestamp, but the drawback of this is, that it is
142          * not possible to sign more than one identical document within
143          * one second.  Some remote batch processing applications might
144          * like this feature here.
145          *
146          * Note that before 2.0.10, we used RIPE-MD160 for the hash
147          * and accidently didn't include the timestamp and algorithm
148          * information in the hash.  Given that this feature is not
149          * commonly used and that a replay attacks detection should
150          * not solely be based on this feature (because it does not
151          * work with RSA), we take the freedom and switch to SHA-1
152          * with 2.0.10 to take advantage of hardware supported SHA-1
153          * implementations.  We also include the missing information
154          * in the hash.  Note also the SIG_ID as computed by gpg 1.x
155          * and gpg 2.x didn't matched either because 2.x used to print
156          * MPIs not in PGP format.  */
157         u32 a = sig->timestamp;
158         int nsig = pubkey_get_nsig( sig->pubkey_algo );
159         unsigned char *p, *buffer;
160         size_t n, nbytes;
161         int i;
162         char hashbuf[20];
163
164         nbytes = 6;
165         for (i=0; i < nsig; i++ )
166           {
167             if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &n, sig->data[i]))
168               BUG();
169             nbytes += n;
170           }
171
172         /* Make buffer large enough to be later used as output buffer.  */
173         if (nbytes < 100)
174           nbytes = 100;
175         nbytes += 10;  /* Safety margin.  */
176
177         /* Fill and hash buffer.  */
178         buffer = p = xmalloc (nbytes);
179         *p++ = sig->pubkey_algo;
180         *p++ = sig->digest_algo;
181         *p++ = (a >> 24) & 0xff;
182         *p++ = (a >> 16) & 0xff;
183         *p++ = (a >>  8) & 0xff;
184         *p++ =  a & 0xff;
185         nbytes -= 6;
186         for (i=0; i < nsig; i++ )
187           {
188             if (gcry_mpi_print (GCRYMPI_FMT_PGP, p, nbytes, &n, sig->data[i]))
189               BUG();
190             p += n;
191             nbytes -= n;
192           }
193         gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf, buffer, p-buffer);
194
195         p = make_radix64_string (hashbuf, 20);
196         sprintf (buffer, "%s %s %lu",
197                  p, strtimestamp (sig->timestamp), (ulong)sig->timestamp);
198         xfree (p);
199         write_status_text (STATUS_SIG_ID, buffer);
200         xfree (buffer);
201     }
202
203     return rc;
204 }
205
206
207 static int
208 do_check_messages( PKT_public_key *pk, PKT_signature *sig,
209                    int *r_expired, int *r_revoked )
210 {
211     u32 cur_time;
212
213     if(r_expired)
214       *r_expired = 0;
215     if(r_revoked)
216       *r_revoked = 0;
217
218     if( pk->timestamp > sig->timestamp )
219       {
220         ulong d = pk->timestamp - sig->timestamp;
221         log_info(d==1
222                  ?_("public key %s is %lu second newer than the signature\n")
223                  :_("public key %s is %lu seconds newer than the signature\n"),
224                  keystr_from_pk(pk),d );
225         if( !opt.ignore_time_conflict )
226           return GPG_ERR_TIME_CONFLICT; /* pubkey newer than signature.  */
227       }
228
229     cur_time = make_timestamp();
230     if( pk->timestamp > cur_time )
231       {
232         ulong d = pk->timestamp - cur_time;
233         log_info( d==1
234                   ? _("key %s was created %lu second"
235                       " in the future (time warp or clock problem)\n")
236                   : _("key %s was created %lu seconds"
237                       " in the future (time warp or clock problem)\n"),
238                   keystr_from_pk(pk),d );
239         if( !opt.ignore_time_conflict )
240           return GPG_ERR_TIME_CONFLICT;
241       }
242
243     /* Check whether the key has expired.  We check the has_expired
244        flag which is set after a full evaluation of the key (getkey.c)
245        as well as a simple compare to the current time in case the
246        merge has for whatever reasons not been done.  */
247     if( pk->has_expired || (pk->expiredate && pk->expiredate < cur_time)) {
248         char buf[11];
249         if (opt.verbose)
250           log_info(_("Note: signature key %s expired %s\n"),
251                    keystr_from_pk(pk), asctimestamp( pk->expiredate ) );
252         sprintf(buf,"%lu",(ulong)pk->expiredate);
253         write_status_text(STATUS_KEYEXPIRED,buf);
254         if(r_expired)
255           *r_expired = 1;
256     }
257
258     if (pk->flags.revoked)
259       {
260         if (opt.verbose)
261           log_info (_("Note: signature key %s has been revoked\n"),
262                     keystr_from_pk(pk));
263         if (r_revoked)
264           *r_revoked=1;
265       }
266
267     return 0;
268 }
269
270
271 static int
272 do_check( PKT_public_key *pk, PKT_signature *sig, gcry_md_hd_t digest,
273           int *r_expired, int *r_revoked, PKT_public_key *ret_pk )
274 {
275     gcry_mpi_t result = NULL;
276     int rc = 0;
277
278     if( (rc=do_check_messages(pk,sig,r_expired,r_revoked)) )
279         return rc;
280
281     if (sig->digest_algo == GCRY_MD_MD5
282         && !opt.flags.allow_weak_digest_algos)
283       {
284         print_md5_rejected_note ();
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, digest, sig->digest_algo );
334     if (!result)
335         return GPG_ERR_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 = GPG_ERR_BAD_SIGNATURE;
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 GPG_ERR_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;
424   int rc = GPG_ERR_GENERAL;
425
426   assert(IS_KEY_REV(sig));
427   assert((sig->keyid[0]!=pk->keyid[0]) || (sig->keyid[0]!=pk->keyid[1]));
428
429   if (busy)
430     {
431       /* Return an error (i.e. not revoked), but mark the pk as
432          uncacheable as we don't really know its revocation status
433          until it is checked directly.  */
434       pk->flags.dont_cache = 1;
435       return rc;
436     }
437
438   busy=1;
439
440   /*  es_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 = GPG_ERR_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 = GPG_ERR_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 = GPG_ERR_SIG_CLASS;
678           }
679     }
680
681     return rc;
682 }