* server.c (option_handler): Allow to use -2 for "send all certs
[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 static KsbaCert
65 get_default_signer (void)
66 {
67   //  const char key[] = "1.2.840.113549.1.9.1=#7472757374407765622E6465#,CN=WEB.DE TrustCenter,OU=TrustCenter,O=WEB.DE AG,L=D-76227 Karlsruhe,C=DE";
68   const char key[] =
69     "/CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=Düsseldorf,C=DE";
70
71   KEYDB_SEARCH_DESC desc;
72   KsbaCert cert = NULL;
73   KEYDB_HANDLE kh = NULL;
74   int rc;
75
76   rc = keydb_classify_name (key, &desc);
77   if (rc)
78     {
79       log_error ("failed to find default signer: %s\n", gnupg_strerror (rc));
80       return NULL;
81     }
82
83   kh = keydb_new (0);
84   if (!kh)
85     return NULL;
86
87   rc = keydb_search (kh, &desc, 1);
88   if (rc)
89     {
90       log_debug ("failed to find default certificate: rc=%d\n", rc);
91     }
92   else 
93     {
94       rc = keydb_get_cert (kh, &cert);
95       if (rc)
96         {
97           log_debug ("failed to get cert: rc=%d\n", rc);
98         }
99     }
100
101   keydb_release (kh);
102   return cert;
103 }
104
105
106 /* Depending on the options in CTRL add the certificate CERT as well as
107    other certificate up in the chain to the Root-CA to the CMS
108    object. */
109 static int 
110 add_certificate_list (CTRL ctrl, KsbaCMS cms, KsbaCert cert)
111 {
112   KsbaError err;
113   int rc = 0;
114   KsbaCert next = NULL;
115   int n;
116   int not_root = 0;
117
118   ksba_cert_ref (cert);
119
120   n = ctrl->include_certs;
121   if (n == -2)
122     {
123       not_root = 1;
124       n = -1;
125     }
126   if (n < 0 || n > 50)
127     n = 50; /* We better apply an upper bound */
128
129   if (n)
130     {
131       if (not_root && gpgsm_is_root_cert (cert))
132         err = 0;
133       else
134         err = ksba_cms_add_cert (cms, cert);
135       if (err)
136         goto ksba_failure;
137     }
138   while ( n-- && !(rc = gpgsm_walk_cert_chain (cert, &next)) )
139     {
140       if (not_root && gpgsm_is_root_cert (next))
141         err = 0;
142       else
143         err = ksba_cms_add_cert (cms, next);
144       ksba_cert_release (cert);
145       cert = next; next = NULL;
146       if (err)
147         goto ksba_failure;
148     }
149   ksba_cert_release (cert);
150
151   return rc == -1? 0: rc;
152
153  ksba_failure:
154   ksba_cert_release (cert);
155   log_error ("ksba_cms_add_cert failed: %s\n", ksba_strerror (err));
156   return map_ksba_err (err);
157 }
158
159
160
161 \f
162 /* Perform a sign operation.  
163
164    Sign the data received on DATA-FD in embedded mode or in deatched
165    mode when DETACHED is true.  Write the signature to OUT_FP The key
166    used to sign is the default - we will extend the fucntion to take a
167    list of fingerprints in the future. */
168 int
169 gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
170 {
171   int i, rc;
172   KsbaError err;
173   Base64Context b64writer = NULL;
174   KsbaWriter writer;
175   KsbaCMS cms = NULL;
176   KsbaStopReason stopreason;
177   KsbaCert cert = NULL;
178   KEYDB_HANDLE kh = NULL;
179   GCRY_MD_HD data_md = NULL;
180   int signer;
181   const char *algoid;
182   int algo;
183   time_t signed_at;
184
185   if (!detached)
186     {
187        rc = seterr (Not_Implemented);
188        goto leave;
189     }
190
191
192   kh = keydb_new (0);
193   if (!kh)
194     {
195       log_error (_("failed to allocated keyDB handle\n"));
196       rc = GNUPG_General_Error;
197       goto leave;
198     }
199
200   ctrl->pem_name = "SIGNED MESSAGE";
201   rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, &writer);
202   if (rc)
203     {
204       log_error ("can't create writer: %s\n", gnupg_strerror (rc));
205       goto leave;
206     }
207
208   cms = ksba_cms_new ();
209   if (!cms)
210     {
211       rc = seterr (Out_Of_Core);
212       goto leave;
213     }
214
215   err = ksba_cms_set_reader_writer (cms, NULL, writer);
216   if (err)
217     {
218       log_debug ("ksba_cms_set_reader_writer failed: %s\n",
219                  ksba_strerror (err));
220       rc = map_ksba_err (err);
221       goto leave;
222     }
223
224   /* We are going to create signed data with data as encap. content */
225   err = ksba_cms_set_content_type (cms, 0, KSBA_CT_SIGNED_DATA);
226   if (!err)
227     err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA);
228   if (err)
229     {
230       log_debug ("ksba_cms_set_content_type failed: %s\n",
231                  ksba_strerror (err));
232       rc = map_ksba_err (err);
233       goto leave;
234     }
235
236
237   /* gather certificates of signers  and store in theCMS object */
238   /* fixme: process a list of fingerprints and store the certificate of
239      each given fingerprint */
240   cert = get_default_signer ();
241   if (!cert)
242     {
243       log_error ("no default signer found\n");
244       rc = seterr (General_Error);
245       goto leave;
246     }
247   err = ksba_cms_add_signer (cms, cert);
248   if (err)
249     {
250       log_error ("ksba_cms_add_signer failed: %s\n",  ksba_strerror (err));
251       rc = map_ksba_err (err);
252       goto leave;
253     }
254   rc = add_certificate_list (ctrl, cms, cert);
255   if (rc)
256     {
257       log_error ("failed to store list of certificates: %s\n",
258                  gnupg_strerror(rc));
259       goto leave;
260     }
261   ksba_cert_release (cert); cert = NULL;
262
263   
264   /* Set the hash algorithm we are going to use */
265   err = ksba_cms_add_digest_algo (cms, "1.3.14.3.2.26" /*SHA-1*/);
266   if (err)
267     {
268       log_debug ("ksba_cms_add_digest_algo failed: %s\n", ksba_strerror (err));
269       rc = map_ksba_err (err);
270       goto leave;
271     }
272
273   /* Prepare hashing (actually we are figuring out what we have set above)*/
274   data_md = gcry_md_open (0, 0);
275   if (!data_md)
276     {
277       rc = map_gcry_err (gcry_errno());
278       log_error ("md_open failed: %s\n", gcry_strerror (-1));
279       goto leave;
280     }
281   if (DBG_HASHING)
282     gcry_md_start_debug (data_md, "sign.data");
283
284   for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++)
285     {
286       algo = gcry_md_map_name (algoid);
287       if (!algo)
288         {
289           log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?");
290           rc = GNUPG_Bug;
291           goto leave;
292         }
293       gcry_md_enable (data_md, algo);
294     }
295
296   signer = 0;
297   if (detached)
298     { /* we hash the data right now so that we can store the message
299          digest.  ksba_cms_build() takes this as an flag that detached
300          data is expected. */
301       unsigned char *digest;
302       size_t digest_len;
303       /* Fixme do this for all signers and get the algo to use from
304          the signer's certificate - does not make mich sense, bu we
305          should do this consistent as we have already done it above */
306       algo = GCRY_MD_SHA1; 
307       hash_data (data_fd, data_md);
308       digest = gcry_md_read (data_md, algo);
309       digest_len = gcry_md_get_algo_dlen (algo);
310       if ( !digest || !digest_len)
311         {
312           log_error ("problem getting the hash of the data\n");
313           rc = GNUPG_Bug;
314           goto leave;
315         }
316       err = ksba_cms_set_message_digest (cms, signer, digest, digest_len);
317       if (err)
318         {
319           log_error ("ksba_cms_set_message_digest failed: %s\n",
320                      ksba_strerror (err));
321           rc = map_ksba_err (err);
322           goto leave;
323         }
324     }
325
326   signed_at = time (NULL);
327   err = ksba_cms_set_signing_time (cms, signer, signed_at);
328   if (err)
329     {
330       log_error ("ksba_cms_set_signing_time failed: %s\n",
331                  ksba_strerror (err));
332       rc = map_ksba_err (err);
333       goto leave;
334     }
335
336   do 
337     {
338       err = ksba_cms_build (cms, &stopreason);
339       if (err)
340         {
341           log_debug ("ksba_cms_build failed: %s\n", ksba_strerror (err));
342           rc = map_ksba_err (err);
343           goto leave;
344         }
345
346       if (stopreason == KSBA_SR_BEGIN_DATA)
347         { /* hash the data and store the message digest */
348           assert (!detached);
349         }
350       else if (stopreason == KSBA_SR_NEED_SIG)
351         { /* calculate the signature for all signers */
352           GCRY_MD_HD md;
353
354           algo = GCRY_MD_SHA1;
355           signer = 0;
356           md = gcry_md_open (algo, 0);
357           if (DBG_HASHING)
358             gcry_md_start_debug (md, "sign.attr");
359
360           if (!md)
361             {
362               log_error ("md_open failed: %s\n", gcry_strerror (-1));
363               goto leave;
364             }
365           ksba_cms_set_hash_function (cms, HASH_FNC, md);
366           rc = ksba_cms_hash_signed_attrs (cms, signer);
367           if (rc)
368             {
369               log_debug ("hashing signed attrs failed: %s\n",
370                          ksba_strerror (rc));
371               gcry_md_close (md);
372               goto leave;
373             }
374           
375           { /* This is all an temporary hack */
376             char *sigval;
377             
378             ksba_cert_release (cert); 
379             cert = get_default_signer ();
380             if (!cert)
381               {
382                 log_error ("oops - failed to get cert again\n");
383                 rc = seterr (General_Error);
384                 goto leave;
385               }
386
387             sigval = NULL;
388             rc = gpgsm_create_cms_signature (cert, md, algo, &sigval);
389             if (rc)
390               goto leave;
391
392             err = ksba_cms_set_sig_val (cms, signer, sigval);
393             xfree (sigval);
394             if (err)
395               {
396                 log_error ("failed to store the signature: %s\n",
397                            ksba_strerror (err));
398                 rc = map_ksba_err (err);
399                 goto leave;
400               }
401
402             /* And write a status message */
403             {
404               char *buf, *fpr;
405               
406               fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
407               if (!fpr)
408                 {
409                   rc = seterr (Out_Of_Core);
410                   goto leave;
411                 }
412               rc = asprintf (&buf, "%c %d %d 00 %lu %s",
413                         detached? 'D':'S',
414                         GCRY_PK_RSA,  /* FIXME: get pk algo from cert */
415                         algo, 
416                         (ulong)signed_at,
417                         fpr);
418               xfree (fpr);
419               if (rc < 0)
420                 {
421                   rc = seterr (Out_Of_Core);
422                   goto leave;
423                 }
424               rc = 0;
425               gpgsm_status (ctrl, STATUS_SIG_CREATED, buf );
426               free (buf); /* yes, we must use the regular free() here */
427             }
428
429           }
430         }
431     }
432   while (stopreason != KSBA_SR_READY);   
433
434   rc = gpgsm_finish_writer (b64writer);
435   if (rc) 
436     {
437       log_error ("write failed: %s\n", gnupg_strerror (rc));
438       goto leave;
439     }
440
441   log_info ("signature created\n");
442
443
444  leave:
445   ksba_cert_release (cert); 
446   ksba_cms_release (cms);
447   gpgsm_destroy_writer (b64writer);
448   keydb_release (kh); 
449   gcry_md_close (data_md);
450   return rc;
451 }