Moved 1.9 branch to trunk
[gnupg.git] / g10 / keyid.c
1 /* keyid.c - key ID and fingerprint handling
2  * Copyright (C) 1998, 1999, 2000, 2001, 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 2 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, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20  * USA.
21  */
22
23 #include <config.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <time.h>
29 #include <assert.h>
30
31 #include "gpg.h"
32 #include "util.h"
33 #include "main.h"
34 #include "packet.h"
35 #include "options.h"
36 #include "keydb.h"
37 #include "i18n.h"
38
39 int
40 pubkey_letter( int algo )
41 {
42     switch( algo ) {
43       case PUBKEY_ALGO_RSA:     return 'R' ;
44       case PUBKEY_ALGO_RSA_E:   return 'r' ;
45       case PUBKEY_ALGO_RSA_S:   return 's' ;
46       case PUBKEY_ALGO_ELGAMAL_E: return 'g';
47       case PUBKEY_ALGO_ELGAMAL: return 'G' ;
48       case PUBKEY_ALGO_DSA:     return 'D' ;
49       default: return '?';
50     }
51 }
52
53 /* This function is useful for v4 fingerprints and v3 or v4 key
54    signing. */
55 void
56 hash_public_key( gcry_md_hd_t md, PKT_public_key *pk )
57 {
58   unsigned int n = 6;
59   unsigned int nn[PUBKEY_MAX_NPKEY];
60   byte *pp[PUBKEY_MAX_NPKEY];
61   int i;
62   size_t nbits, nbytes;
63   int npkey = pubkey_get_npkey (pk->pubkey_algo);
64
65   /* Two extra bytes for the expiration date in v3 */
66   if(pk->version<4)
67     n+=2;
68
69   if (npkey==0 && pk->pkey[0]
70       && gcry_mpi_get_flag (pk->pkey[0], GCRYMPI_FLAG_OPAQUE))
71     {
72       pp[0] = gcry_mpi_get_opaque (pk->pkey[0], &nbits);
73       nn[0] = (nbits+7)/8;
74       n+=nn[0];
75     }
76   else
77     for(i=0; i < npkey; i++ )
78       {
79         if (gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, pk->pkey[i]))
80           BUG ();
81         pp[i] = xmalloc (nbytes);
82         if (gcry_mpi_print (GCRYMPI_FMT_PGP, pp[i], nbytes,
83                             &nbytes, pk->pkey[i]))
84           BUG ();
85         nn[i] = nbytes;
86         n += nn[i];
87       }
88
89   gcry_md_putc ( md, 0x99 );     /* ctb */
90   /* What does it mean if n is greater than than 0xFFFF ? */
91   gcry_md_putc ( md, n >> 8 );   /* 2 byte length header */
92   gcry_md_putc ( md, n );
93   gcry_md_putc ( md, pk->version );
94
95   gcry_md_putc ( md, pk->timestamp >> 24 );
96   gcry_md_putc ( md, pk->timestamp >> 16 );
97   gcry_md_putc ( md, pk->timestamp >>  8 );
98   gcry_md_putc ( md, pk->timestamp       );
99
100   if(pk->version<4)
101     {
102       u16 days=0;
103       if(pk->expiredate)
104         days=(u16)((pk->expiredate - pk->timestamp) / 86400L);
105  
106       gcry_md_putc ( md, days >> 8 );
107       gcry_md_putc ( md, days );
108     }
109
110   gcry_md_putc ( md, pk->pubkey_algo );
111
112   if(npkey==0 && pk->pkey[0]
113      && gcry_mpi_get_flag (pk->pkey[0], GCRYMPI_FLAG_OPAQUE))
114     {
115       gcry_md_write (md, pp[0], nn[0]);
116     }
117   else
118     for(i=0; i < npkey; i++ )
119       {
120         gcry_md_write ( md, pp[i], nn[i] );
121         xfree(pp[i]);
122       }
123 }
124
125 static gcry_md_hd_t
126 do_fingerprint_md( PKT_public_key *pk )
127 {
128   gcry_md_hd_t md;
129
130   if (gcry_md_open (&md, DIGEST_ALGO_SHA1, 0))
131     BUG ();
132   hash_public_key(md,pk);
133   gcry_md_final( md );
134
135   return md;
136 }
137
138 static gcry_md_hd_t
139 do_fingerprint_md_sk( PKT_secret_key *sk )
140 {
141     PKT_public_key pk;
142     int npkey = pubkey_get_npkey( sk->pubkey_algo ); /* npkey is correct! */
143     int i;
144
145     if(npkey==0)
146       return NULL;
147
148     pk.pubkey_algo = sk->pubkey_algo;
149     pk.version     = sk->version;
150     pk.timestamp = sk->timestamp;
151     pk.expiredate = sk->expiredate;
152     pk.pubkey_algo = sk->pubkey_algo;
153     for( i=0; i < npkey; i++ )
154       pk.pkey[i] = sk->skey[i];
155     return do_fingerprint_md( &pk );
156 }
157
158
159 u32
160 v3_keyid (gcry_mpi_t a, u32 *ki)
161 {
162   byte *buffer;
163   size_t nbytes;
164
165   if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, &nbytes, a ))
166     BUG ();
167   /* fixme: allocate it on the stack */
168   buffer = xmalloc (nbytes);
169   if (gcry_mpi_print( GCRYMPI_FMT_USG, buffer, nbytes, NULL, a ))
170     BUG ();
171   if (nbytes < 8) /* oops */
172     ki[0] = ki[1] = 0;
173   else 
174     {
175       memcpy (ki+0, buffer+nbytes-8, 4);
176       memcpy (ki+1, buffer+nbytes-4, 4);
177     }
178   xfree (buffer);
179   return ki[1];
180 }
181
182
183 size_t
184 keystrlen(void)
185 {
186   switch(opt.keyid_format)
187     {
188     case KF_SHORT:
189       return 8;
190
191     case KF_LONG:
192       return 16;
193
194     case KF_0xSHORT:
195       return 10;
196
197     case KF_0xLONG:
198       return 18;
199
200     default:
201       BUG();
202     }
203 }
204
205 const char *
206 keystr(u32 *keyid)
207 {  
208   static char keyid_str[19];
209
210   switch(opt.keyid_format)
211     {
212     case KF_SHORT:
213       sprintf(keyid_str,"%08lX",(ulong)keyid[1]);
214       break;
215
216     case KF_LONG:
217       if(keyid[0])
218         sprintf(keyid_str,"%08lX%08lX",(ulong)keyid[0],(ulong)keyid[1]);
219       else
220         sprintf(keyid_str,"%08lX",(ulong)keyid[1]);
221       break;
222
223     case KF_0xSHORT:
224       sprintf(keyid_str,"0x%08lX",(ulong)keyid[1]);
225       break;
226
227     case KF_0xLONG:
228       if(keyid[0])
229         sprintf(keyid_str,"0x%08lX%08lX",(ulong)keyid[0],(ulong)keyid[1]);
230       else
231         sprintf(keyid_str,"0x%08lX",(ulong)keyid[1]);
232       break;
233
234     default:
235       BUG();
236     }
237
238   return keyid_str;
239 }
240
241 const char *
242 keystr_from_pk(PKT_public_key *pk)
243 {
244   keyid_from_pk(pk,NULL);
245
246   return keystr(pk->keyid);
247 }
248
249 const char *
250 keystr_from_sk(PKT_secret_key *sk)
251 {
252   keyid_from_sk(sk,NULL);
253
254   return keystr(sk->keyid);
255 }
256
257 const char *
258 keystr_from_desc(KEYDB_SEARCH_DESC *desc)
259 {
260   switch(desc->mode)
261     {
262     case KEYDB_SEARCH_MODE_LONG_KID:
263     case KEYDB_SEARCH_MODE_SHORT_KID:
264       return keystr(desc->u.kid);
265
266     case KEYDB_SEARCH_MODE_FPR20:
267       {
268         u32 keyid[2];
269
270         keyid[0] = ((unsigned char)desc->u.fpr[12] << 24
271                     | (unsigned char)desc->u.fpr[13] << 16
272                     | (unsigned char)desc->u.fpr[14] << 8
273                     | (unsigned char)desc->u.fpr[15]);
274         keyid[1] = ((unsigned char)desc->u.fpr[16] << 24
275                     | (unsigned char)desc->u.fpr[17] << 16
276                     | (unsigned char)desc->u.fpr[18] << 8
277                     | (unsigned char)desc->u.fpr[19]);
278
279         return keystr(keyid);
280       }
281
282     case KEYDB_SEARCH_MODE_FPR16:
283       return "?v3 fpr?";
284
285     default:
286       BUG();
287     }
288 }
289
290 /****************
291  * Get the keyid from the secret key and put it into keyid
292  * if this is not NULL. Return the 32 low bits of the keyid.
293  */
294 u32
295 keyid_from_sk( PKT_secret_key *sk, u32 *keyid )
296 {
297   u32 lowbits;
298   u32 dummy_keyid[2];
299
300   if( !keyid )
301     keyid = dummy_keyid;
302
303   if( sk->keyid[0] || sk->keyid[1] )
304     {
305       keyid[0] = sk->keyid[0];
306       keyid[1] = sk->keyid[1];
307       lowbits = keyid[1];
308     }
309   else if( sk->version < 4 )
310     {
311       if( is_RSA(sk->pubkey_algo) )
312         {
313           lowbits = (pubkey_get_npkey (sk->pubkey_algo) ?
314                      v3_keyid( sk->skey[0], keyid ) : 0); /* Take n. */
315           sk->keyid[0]=keyid[0];
316           sk->keyid[1]=keyid[1];
317         }
318       else
319         sk->keyid[0]=sk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF;
320     }
321   else
322     {
323       const byte *dp;
324       gcry_md_hd_t md;
325
326       md = do_fingerprint_md_sk(sk);
327       if(md)
328         {
329           dp = gcry_md_read (md, 0);
330           keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
331           keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
332           lowbits = keyid[1];
333           gcry_md_close (md);
334           sk->keyid[0] = keyid[0];
335           sk->keyid[1] = keyid[1];
336         }
337       else
338         sk->keyid[0]=sk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF;
339     }
340
341   return lowbits;
342 }
343
344
345 /****************
346  * Get the keyid from the public key and put it into keyid
347  * if this is not NULL. Return the 32 low bits of the keyid.
348  */
349 u32
350 keyid_from_pk( PKT_public_key *pk, u32 *keyid )
351 {
352   u32 lowbits;
353   u32 dummy_keyid[2];
354
355   if( !keyid )
356     keyid = dummy_keyid;
357
358   if( pk->keyid[0] || pk->keyid[1] )
359     {
360       keyid[0] = pk->keyid[0];
361       keyid[1] = pk->keyid[1];
362       lowbits = keyid[1];
363     }
364   else if( pk->version < 4 )
365     {
366       if( is_RSA(pk->pubkey_algo) )
367         {
368           lowbits = (pubkey_get_npkey (pk->pubkey_algo) ?
369                      v3_keyid ( pk->pkey[0], keyid ) : 0); /* From n. */
370           pk->keyid[0] = keyid[0];
371           pk->keyid[1] = keyid[1];
372         }
373       else
374         pk->keyid[0]=pk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF;
375     }
376   else
377     {
378       const byte *dp;
379       gcry_md_hd_t md;
380
381       md = do_fingerprint_md(pk);
382       if(md)
383         {
384           dp = gcry_md_read ( md, 0 );
385           keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
386           keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
387           lowbits = keyid[1];
388           gcry_md_close (md);
389           pk->keyid[0] = keyid[0];
390           pk->keyid[1] = keyid[1];
391         }
392       else
393         pk->keyid[0]=pk->keyid[1]=keyid[0]=keyid[1]=lowbits=0xFFFFFFFF;
394     }
395
396   return lowbits;
397 }
398
399
400 /****************
401  * Get the keyid from the fingerprint.  This function is simple for most
402  * keys, but has to do a keylookup for old stayle keys.
403  */
404 u32
405 keyid_from_fingerprint( const byte *fprint, size_t fprint_len, u32 *keyid )
406 {
407     u32 dummy_keyid[2];
408
409     if( !keyid )
410         keyid = dummy_keyid;
411
412     if( fprint_len != 20 ) {
413         /* This is special as we have to lookup the key first */
414         PKT_public_key pk;
415         int rc;
416
417         memset( &pk, 0, sizeof pk );
418         rc = get_pubkey_byfprint( &pk, fprint, fprint_len );
419         if( rc ) {
420             log_error("Oops: keyid_from_fingerprint: no pubkey\n");
421             keyid[0] = 0;
422             keyid[1] = 0;
423         }
424         else
425             keyid_from_pk( &pk, keyid );
426     }
427     else {
428         const byte *dp = fprint;
429         keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
430         keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
431     }
432
433     return keyid[1];
434 }
435
436
437 u32
438 keyid_from_sig( PKT_signature *sig, u32 *keyid )
439 {
440     if( keyid ) {
441         keyid[0] = sig->keyid[0];
442         keyid[1] = sig->keyid[1];
443     }
444     return sig->keyid[1];
445 }
446
447 byte *
448 namehash_from_uid(PKT_user_id *uid)
449 {
450   if(uid->namehash==NULL)
451     {
452       uid->namehash = xmalloc(20);
453
454       if(uid->attrib_data)
455         gcry_md_hash_buffer (GCRY_MD_RMD160, uid->namehash,
456                              uid->attrib_data, uid->attrib_len);
457       else
458         gcry_md_hash_buffer (GCRY_MD_RMD160, uid->namehash,
459                              uid->name, uid->len);
460     }
461   
462   return uid->namehash;
463 }
464
465 /****************
466  * return the number of bits used in the pk
467  */
468 unsigned
469 nbits_from_pk( PKT_public_key *pk )
470 {
471     return pubkey_nbits( pk->pubkey_algo, pk->pkey );
472 }
473
474 /****************
475  * return the number of bits used in the sk
476  */
477 unsigned
478 nbits_from_sk( PKT_secret_key *sk )
479 {
480     return pubkey_nbits( sk->pubkey_algo, sk->skey );
481 }
482
483 static const char *
484 mk_datestr (char *buffer, time_t atime)
485 {
486     struct tm *tp;
487
488     if ( atime < 0 ) /* 32 bit time_t and after 2038-01-19 */
489         strcpy (buffer, "????" "-??" "-??"); /* mark this as invalid */
490     else {
491         tp = gmtime (&atime);
492         sprintf (buffer,"%04d-%02d-%02d",
493                  1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday );
494     }
495     return buffer;
496 }
497
498 /****************
499  * return a string with the creation date of the pk
500  * Note: this is alloced in a static buffer.
501  *    Format is: yyyy-mm-dd
502  */
503 const char *
504 datestr_from_pk( PKT_public_key *pk )
505 {
506     static char buffer[11+5];
507     time_t atime = pk->timestamp;
508
509     return mk_datestr (buffer, atime);
510 }
511
512 const char *
513 datestr_from_sk( PKT_secret_key *sk )
514 {
515     static char buffer[11+5];
516     time_t atime = sk->timestamp;
517
518     return mk_datestr (buffer, atime);
519 }
520
521 const char *
522 datestr_from_sig( PKT_signature *sig )
523 {
524     static char buffer[11+5];
525     time_t atime = sig->timestamp;
526
527     return mk_datestr (buffer, atime);
528 }
529
530 const char *
531 expirestr_from_pk( PKT_public_key *pk )
532 {
533     static char buffer[11+5];
534     time_t atime;
535
536     if( !pk->expiredate )
537         return _("never     ");
538     atime = pk->expiredate;
539     return mk_datestr (buffer, atime);
540 }
541
542 const char *
543 expirestr_from_sk( PKT_secret_key *sk )
544 {
545     static char buffer[11+5];
546     time_t atime;
547
548     if( !sk->expiredate )
549         return _("never     ");
550     atime = sk->expiredate;
551     return mk_datestr (buffer, atime);
552 }
553
554 const char *
555 expirestr_from_sig( PKT_signature *sig )
556 {
557     static char buffer[11+5];
558     time_t atime;
559
560     if(!sig->expiredate)
561       return _("never     ");
562     atime=sig->expiredate;
563     return mk_datestr (buffer, atime);
564 }
565
566 const char *
567 revokestr_from_pk( PKT_public_key *pk )
568 {
569     static char buffer[11+5];
570     time_t atime;
571
572     if(!pk->revoked.date)
573       return _("never     ");
574     atime=pk->revoked.date;
575     return mk_datestr (buffer, atime);
576 }
577
578
579 const char *
580 usagestr_from_pk( PKT_public_key *pk )
581 {
582   static char buffer[10];
583   int i = 0;
584   unsigned int use = pk->pubkey_usage;
585
586   if ( use & PUBKEY_USAGE_SIG )
587     buffer[i++] = 'S';
588
589   if ( use & PUBKEY_USAGE_CERT )
590     buffer[i++] = 'C';
591
592   if ( use & PUBKEY_USAGE_ENC )
593     buffer[i++] = 'E';
594
595   if ( (use & PUBKEY_USAGE_AUTH) )
596     buffer[i++] = 'A';
597
598   while (i < 4)
599     buffer[i++] = ' ';
600
601   buffer[i] = 0;
602   return buffer;
603 }
604
605
606 const char *
607 colon_strtime (u32 t)
608 {
609     if (!t)
610         return "";
611     if (opt.fixed_list_mode) {
612         static char buf[15];
613         sprintf (buf, "%lu", (ulong)t);
614         return buf;
615     }
616     return strtimestamp(t);
617 }
618
619 const char *
620 colon_datestr_from_pk (PKT_public_key *pk)
621 {
622     if (opt.fixed_list_mode) {
623         static char buf[15];
624         sprintf (buf, "%lu", (ulong)pk->timestamp);
625         return buf;
626     }
627     return datestr_from_pk (pk);
628 }
629
630 const char *
631 colon_datestr_from_sk (PKT_secret_key *sk)
632 {
633     if (opt.fixed_list_mode) {
634         static char buf[15];
635         sprintf (buf, "%lu", (ulong)sk->timestamp);
636         return buf;
637     }
638     return datestr_from_sk (sk);
639 }
640
641 const char *
642 colon_datestr_from_sig (PKT_signature *sig)
643 {
644     if (opt.fixed_list_mode) {
645         static char buf[15];
646         sprintf (buf, "%lu", (ulong)sig->timestamp);
647         return buf;
648     }
649     return datestr_from_sig (sig);
650 }
651
652 const char *
653 colon_expirestr_from_sig (PKT_signature *sig)
654 {
655     if(!sig->expiredate)
656         return "";
657     if (opt.fixed_list_mode) {
658         static char buf[15];
659         sprintf (buf, "%lu", (ulong)sig->expiredate);
660         return buf;
661     }
662     return expirestr_from_sig (sig);
663 }
664
665
666 /**************** .
667  * Return a byte array with the fingerprint for the given PK/SK
668  * The length of the array is returned in ret_len. Caller must free
669  * the array or provide an array of length MAX_FINGERPRINT_LEN.
670  */
671
672 byte *
673 fingerprint_from_pk( PKT_public_key *pk, byte *array, size_t *ret_len )
674 {
675   byte *buf;
676   const byte *dp;
677   size_t len, nbytes;
678   int i;
679   
680   if ( pk->version < 4 )
681     {
682       if ( is_RSA(pk->pubkey_algo) )
683         {
684           /* RSA in version 3 packets is special. */
685           gcry_md_hd_t md;
686           
687           if (gcry_md_open (&md, DIGEST_ALGO_MD5, 0))
688             BUG ();
689           if ( pubkey_get_npkey (pk->pubkey_algo) > 1 ) 
690             {
691               for (i=0; i < 2; i++)
692                 {
693                   if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, 
694                                       &nbytes, pk->pkey[i]))
695                     BUG ();
696                   /* fixme: Better allocate BUF on the stack */
697                   buf = xmalloc (nbytes);
698                   if (gcry_mpi_print (GCRYMPI_FMT_USG, buf, nbytes,
699                                       NULL, pk->pkey[i]))
700                     BUG ();
701                   gcry_md_write (md, buf, nbytes);
702                   xfree (buf);
703                 }
704             }
705           gcry_md_final (md);
706           if (!array)
707             array = xmalloc (16);
708           len = 16;
709           memcpy (array, gcry_md_read (md, DIGEST_ALGO_MD5), 16);
710           gcry_md_close(md);
711         }
712       else
713         {
714           if (!array)
715             array = xmalloc(16);
716           len = 16;
717           memset (array,0,16);
718         }
719     }
720   else 
721     {
722       gcry_md_hd_t md;
723       
724       md = do_fingerprint_md(pk);
725       dp = gcry_md_read( md, 0 );
726       len = gcry_md_get_algo_dlen (gcry_md_get_algo (md));
727       assert( len <= MAX_FINGERPRINT_LEN );
728       if (!array)
729         array = xmalloc ( len );
730       memcpy (array, dp, len );
731       pk->keyid[0] = dp[12] << 24 | dp[13] << 16 | dp[14] << 8 | dp[15] ;
732       pk->keyid[1] = dp[16] << 24 | dp[17] << 16 | dp[18] << 8 | dp[19] ;
733       gcry_md_close( md);
734     }
735   
736   *ret_len = len;
737   return array;
738 }
739
740 byte *
741 fingerprint_from_sk( PKT_secret_key *sk, byte *array, size_t *ret_len )
742 {
743   byte *buf;
744   const char *dp;
745   size_t len, nbytes;
746   int i;
747   
748   if (sk->version < 4)
749     {
750       if ( is_RSA(sk->pubkey_algo) )
751         {
752           /* RSA in version 3 packets is special. */
753           gcry_md_hd_t md;
754           
755           if (gcry_md_open (&md, DIGEST_ALGO_MD5, 0))
756             BUG ();
757           if (pubkey_get_npkey( sk->pubkey_algo ) > 1)
758             {
759               for (i=0; i < 2; i++)
760                 {
761                   if (gcry_mpi_print (GCRYMPI_FMT_USG, NULL, 0, 
762                                       &nbytes, sk->skey[i]))
763                     BUG ();
764                   /* fixme: Better allocate BUF on the stack */
765                   buf = xmalloc (nbytes);
766                   if (gcry_mpi_print (GCRYMPI_FMT_USG, buf, nbytes,
767                                       NULL, sk->skey[i]))
768                     BUG ();
769                   gcry_md_write (md, buf, nbytes);
770                   xfree (buf);
771                 }
772             }
773           gcry_md_final(md);
774           if (!array)
775             array = xmalloc (16);
776           len = 16;
777           memcpy (array, gcry_md_read (md, DIGEST_ALGO_MD5), 16);
778           gcry_md_close (md);
779         }
780       else
781         {
782           if (!array)
783             array = xmalloc (16);
784           len=16;
785           memset (array,0,16);
786         }
787     }
788   else
789     {
790       gcry_md_hd_t md;
791       
792       md = do_fingerprint_md_sk(sk);
793       if (md)
794         {
795           dp = gcry_md_read ( md, 0 );
796           len = gcry_md_get_algo_dlen ( gcry_md_get_algo (md) );
797           assert ( len <= MAX_FINGERPRINT_LEN );
798           if (!array)
799             array = xmalloc( len );
800           memcpy (array, dp, len);
801           gcry_md_close (md);
802         }
803       else
804         {
805           len = MAX_FINGERPRINT_LEN;
806           if (!array)
807             array = xmalloc (len);
808           memset (array, 0, len);
809         }
810     }
811   
812   *ret_len = len;
813   return array;
814 }