* keylist.c (list_cert_colon): Fixed listing of crt record; the
[gnupg.git] / sm / sign.c
1 /* sign.c - Sign a message
2  *      Copyright (C) 2001 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <unistd.h> 
27 #include <time.h>
28 #include <assert.h>
29
30 #include <gcrypt.h>
31 #include <ksba.h>
32
33 #include "gpgsm.h"
34 #include "keydb.h"
35 #include "i18n.h"
36
37
38 static void
39 hash_data (int fd, GCRY_MD_HD md)
40 {
41   FILE *fp;
42   char buffer[4096];
43   int nread;
44
45   fp = fdopen ( dup (fd), "rb");
46   if (!fp)
47     {
48       log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
49       return;
50     }
51
52   do 
53     {
54       nread = fread (buffer, 1, DIM(buffer), fp);
55       gcry_md_write (md, buffer, nread);
56     }
57   while (nread);
58   if (ferror (fp))
59       log_error ("read error on fd %d: %s\n", fd, strerror (errno));
60   fclose (fp);
61 }
62
63
64 /* Get the default certificate which is defined as the first one our
65    keyDB retruns and has a secret key available */
66 int
67 gpgsm_get_default_cert (KsbaCert *r_cert)
68 {
69   KEYDB_HANDLE hd;
70   KsbaCert cert = NULL;
71   int rc;
72   char *p;
73
74   hd = keydb_new (0);
75   if (!hd)
76     return GNUPG_General_Error;
77   rc = keydb_search_first (hd);
78   if (rc)
79     {
80       keydb_release (hd);
81       return rc;
82     }
83
84   do
85     {
86       rc = keydb_get_cert (hd, &cert);
87       if (rc) 
88         {
89           log_error ("keydb_get_cert failed: %s\n", gnupg_strerror (rc));
90           keydb_release (hd);
91           return rc;
92         }
93       
94       p = gpgsm_get_keygrip_hexstring (cert);
95       if (p)
96         {
97           if (!gpgsm_agent_havekey (p))
98             {
99               xfree (p);
100               keydb_release (hd);
101               *r_cert = cert;
102               return 0; /* got it */
103             }
104           xfree (p);
105         }
106     
107       ksba_cert_release (cert); 
108       cert = NULL;
109     }
110   while (!(rc = keydb_search_next (hd)));
111   if (rc && rc != -1)
112     log_error ("keydb_search_next failed: %s\n", gnupg_strerror (rc));
113   
114   ksba_cert_release (cert);
115   keydb_release (hd);
116   return rc;
117 }
118
119
120 static KsbaCert
121 get_default_signer (void)
122 {
123   KEYDB_SEARCH_DESC desc;
124   KsbaCert cert = NULL;
125   KEYDB_HANDLE kh = NULL;
126   int rc;
127
128   if (!opt.local_user)
129     {
130       rc = gpgsm_get_default_cert (&cert);
131       if (rc)
132         {
133           if (rc != -1)
134             log_debug ("failed to find default certificate: %s\n",
135                        gnupg_strerror (rc));
136           return NULL;
137         }
138       return cert;
139     }
140
141   rc = keydb_classify_name (opt.local_user, &desc);
142   if (rc)
143     {
144       log_error ("failed to find default signer: %s\n", gnupg_strerror (rc));
145       return NULL;
146     }
147
148   kh = keydb_new (0);
149   if (!kh)
150     return NULL;
151
152   rc = keydb_search (kh, &desc, 1);
153   if (rc)
154     {
155       log_debug ("failed to find default certificate: rc=%d\n", rc);
156     }
157   else 
158     {
159       rc = keydb_get_cert (kh, &cert);
160       if (rc)
161         {
162           log_debug ("failed to get cert: rc=%d\n", rc);
163         }
164     }
165
166   keydb_release (kh);
167   return cert;
168 }
169
170
171
172 /* Depending on the options in CTRL add the certificate CERT as well as
173    other certificate up in the chain to the Root-CA to the CMS
174    object. */
175 static int 
176 add_certificate_list (CTRL ctrl, KsbaCMS cms, KsbaCert cert)
177 {
178   KsbaError err;
179   int rc = 0;
180   KsbaCert next = NULL;
181   int n;
182   int not_root = 0;
183
184   ksba_cert_ref (cert);
185
186   n = ctrl->include_certs;
187   if (n == -2)
188     {
189       not_root = 1;
190       n = -1;
191     }
192   if (n < 0 || n > 50)
193     n = 50; /* We better apply an upper bound */
194
195   if (n)
196     {
197       if (not_root && gpgsm_is_root_cert (cert))
198         err = 0;
199       else
200         err = ksba_cms_add_cert (cms, cert);
201       if (err)
202         goto ksba_failure;
203     }
204   while ( n-- && !(rc = gpgsm_walk_cert_chain (cert, &next)) )
205     {
206       if (not_root && gpgsm_is_root_cert (next))
207         err = 0;
208       else
209         err = ksba_cms_add_cert (cms, next);
210       ksba_cert_release (cert);
211       cert = next; next = NULL;
212       if (err)
213         goto ksba_failure;
214     }
215   ksba_cert_release (cert);
216
217   return rc == -1? 0: rc;
218
219  ksba_failure:
220   ksba_cert_release (cert);
221   log_error ("ksba_cms_add_cert failed: %s\n", ksba_strerror (err));
222   return map_ksba_err (err);
223 }
224
225
226
227 \f
228 /* Perform a sign operation.  
229
230    Sign the data received on DATA-FD in embedded mode or in deatched
231    mode when DETACHED is true.  Write the signature to OUT_FP The key
232    used to sign is the default - we will extend the fucntion to take a
233    list of fingerprints in the future. */
234 int
235 gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
236 {
237   int i, rc;
238   KsbaError err;
239   Base64Context b64writer = NULL;
240   KsbaWriter writer;
241   KsbaCMS cms = NULL;
242   KsbaStopReason stopreason;
243   KsbaCert cert = NULL;
244   KEYDB_HANDLE kh = NULL;
245   GCRY_MD_HD data_md = NULL;
246   int signer;
247   const char *algoid;
248   int algo;
249   time_t signed_at;
250
251   if (!detached)
252     {
253        rc = seterr (Not_Implemented);
254        goto leave;
255     }
256
257
258   kh = keydb_new (0);
259   if (!kh)
260     {
261       log_error (_("failed to allocated keyDB handle\n"));
262       rc = GNUPG_General_Error;
263       goto leave;
264     }
265
266   ctrl->pem_name = "SIGNED MESSAGE";
267   rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
268   if (rc)
269     {
270       log_error ("can't create writer: %s\n", gnupg_strerror (rc));
271       goto leave;
272     }
273
274   cms = ksba_cms_new ();
275   if (!cms)
276     {
277       rc = seterr (Out_Of_Core);
278       goto leave;
279     }
280
281   err = ksba_cms_set_reader_writer (cms, NULL, writer);
282   if (err)
283     {
284       log_debug ("ksba_cms_set_reader_writer failed: %s\n",
285                  ksba_strerror (err));
286       rc = map_ksba_err (err);
287       goto leave;
288     }
289
290   /* We are going to create signed data with data as encap. content */
291   err = ksba_cms_set_content_type (cms, 0, KSBA_CT_SIGNED_DATA);
292   if (!err)
293     err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA);
294   if (err)
295     {
296       log_debug ("ksba_cms_set_content_type failed: %s\n",
297                  ksba_strerror (err));
298       rc = map_ksba_err (err);
299       goto leave;
300     }
301
302
303   /* gather certificates of signers  and store in theCMS object */
304   /* fixme: process a list of fingerprints and store the certificate of
305      each given fingerprint */
306   cert = get_default_signer ();
307   if (!cert)
308     {
309       log_error ("no default signer found\n");
310       rc = seterr (General_Error);
311       goto leave;
312     }
313   err = ksba_cms_add_signer (cms, cert);
314   if (err)
315     {
316       log_error ("ksba_cms_add_signer failed: %s\n",  ksba_strerror (err));
317       rc = map_ksba_err (err);
318       goto leave;
319     }
320   rc = add_certificate_list (ctrl, cms, cert);
321   if (rc)
322     {
323       log_error ("failed to store list of certificates: %s\n",
324                  gnupg_strerror(rc));
325       goto leave;
326     }
327   ksba_cert_release (cert); cert = NULL;
328
329   
330   /* Set the hash algorithm we are going to use */
331   err = ksba_cms_add_digest_algo (cms, "1.3.14.3.2.26" /*SHA-1*/);
332   if (err)
333     {
334       log_debug ("ksba_cms_add_digest_algo failed: %s\n", ksba_strerror (err));
335       rc = map_ksba_err (err);
336       goto leave;
337     }
338
339   /* Prepare hashing (actually we are figuring out what we have set above)*/
340   data_md = gcry_md_open (0, 0);
341   if (!data_md)
342     {
343       rc = map_gcry_err (gcry_errno());
344       log_error ("md_open failed: %s\n", gcry_strerror (-1));
345       goto leave;
346     }
347   if (DBG_HASHING)
348     gcry_md_start_debug (data_md, "sign.data");
349
350   for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++)
351     {
352       algo = gcry_md_map_name (algoid);
353       if (!algo)
354         {
355           log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?");
356           rc = GNUPG_Bug;
357           goto leave;
358         }
359       gcry_md_enable (data_md, algo);
360     }
361
362   signer = 0;
363   if (detached)
364     { /* we hash the data right now so that we can store the message
365          digest.  ksba_cms_build() takes this as an flag that detached
366          data is expected. */
367       unsigned char *digest;
368       size_t digest_len;
369       /* Fixme do this for all signers and get the algo to use from
370          the signer's certificate - does not make mich sense, bu we
371          should do this consistent as we have already done it above */
372       algo = GCRY_MD_SHA1; 
373       hash_data (data_fd, data_md);
374       digest = gcry_md_read (data_md, algo);
375       digest_len = gcry_md_get_algo_dlen (algo);
376       if ( !digest || !digest_len)
377         {
378           log_error ("problem getting the hash of the data\n");
379           rc = GNUPG_Bug;
380           goto leave;
381         }
382       err = ksba_cms_set_message_digest (cms, signer, digest, digest_len);
383       if (err)
384         {
385           log_error ("ksba_cms_set_message_digest failed: %s\n",
386                      ksba_strerror (err));
387           rc = map_ksba_err (err);
388           goto leave;
389         }
390     }
391
392   signed_at = time (NULL);
393   err = ksba_cms_set_signing_time (cms, signer, signed_at);
394   if (err)
395     {
396       log_error ("ksba_cms_set_signing_time failed: %s\n",
397                  ksba_strerror (err));
398       rc = map_ksba_err (err);
399       goto leave;
400     }
401
402   do 
403     {
404       err = ksba_cms_build (cms, &stopreason);
405       if (err)
406         {
407           log_debug ("ksba_cms_build failed: %s\n", ksba_strerror (err));
408           rc = map_ksba_err (err);
409           goto leave;
410         }
411
412       if (stopreason == KSBA_SR_BEGIN_DATA)
413         { /* hash the data and store the message digest */
414           assert (!detached);
415         }
416       else if (stopreason == KSBA_SR_NEED_SIG)
417         { /* calculate the signature for all signers */
418           GCRY_MD_HD md;
419
420           algo = GCRY_MD_SHA1;
421           signer = 0;
422           md = gcry_md_open (algo, 0);
423           if (DBG_HASHING)
424             gcry_md_start_debug (md, "sign.attr");
425
426           if (!md)
427             {
428               log_error ("md_open failed: %s\n", gcry_strerror (-1));
429               goto leave;
430             }
431           ksba_cms_set_hash_function (cms, HASH_FNC, md);
432           rc = ksba_cms_hash_signed_attrs (cms, signer);
433           if (rc)
434             {
435               log_debug ("hashing signed attrs failed: %s\n",
436                          ksba_strerror (rc));
437               gcry_md_close (md);
438               goto leave;
439             }
440           
441           { /* This is all an temporary hack */
442             char *sigval;
443             
444             ksba_cert_release (cert); 
445             cert = get_default_signer ();
446             if (!cert)
447               {
448                 log_error ("oops - failed to get cert again\n");
449                 rc = seterr (General_Error);
450                 goto leave;
451               }
452
453             sigval = NULL;
454             rc = gpgsm_create_cms_signature (cert, md, algo, &sigval);
455             if (rc)
456               goto leave;
457
458             err = ksba_cms_set_sig_val (cms, signer, sigval);
459             xfree (sigval);
460             if (err)
461               {
462                 log_error ("failed to store the signature: %s\n",
463                            ksba_strerror (err));
464                 rc = map_ksba_err (err);
465                 goto leave;
466               }
467
468             /* And write a status message */
469             {
470               char *buf, *fpr;
471               
472               fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
473               if (!fpr)
474                 {
475                   rc = seterr (Out_Of_Core);
476                   goto leave;
477                 }
478               rc = asprintf (&buf, "%c %d %d 00 %lu %s",
479                         detached? 'D':'S',
480                         GCRY_PK_RSA,  /* FIXME: get pk algo from cert */
481                         algo, 
482                         (ulong)signed_at,
483                         fpr);
484               xfree (fpr);
485               if (rc < 0)
486                 {
487                   rc = seterr (Out_Of_Core);
488                   goto leave;
489                 }
490               rc = 0;
491               gpgsm_status (ctrl, STATUS_SIG_CREATED, buf );
492               free (buf); /* yes, we must use the regular free() here */
493             }
494
495           }
496         }
497     }
498   while (stopreason != KSBA_SR_READY);   
499
500   rc = gpgsm_finish_writer (b64writer);
501   if (rc) 
502     {
503       log_error ("write failed: %s\n", gnupg_strerror (rc));
504       goto leave;
505     }
506
507   log_info ("signature created\n");
508
509
510  leave:
511   ksba_cert_release (cert); 
512   ksba_cms_release (cms);
513   gpgsm_destroy_writer (b64writer);
514   keydb_release (kh); 
515   gcry_md_close (data_md);
516   return rc;
517 }