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