Fixed a problem in estream-printf.c.
[gnupg.git] / sm / certcheck.c
1 /* certcheck.c - check one certificate
2  *      Copyright (C) 2001, 2003, 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <unistd.h> 
28 #include <time.h>
29 #include <assert.h>
30
31 #include "gpgsm.h"
32 #include <gcrypt.h>
33 #include <ksba.h>
34
35 #include "keydb.h"
36 #include "i18n.h"
37
38
39 /* Remove this if libgcrypt 1.3.0 is required. */
40 #define MY_GCRY_PK_ECDSA  301
41
42
43 /* Return the number of bits of the Q parameter from the DSA key
44    KEY.  */
45 static unsigned int
46 get_dsa_qbits (gcry_sexp_t key)
47 {
48   gcry_sexp_t l1, l2;
49   gcry_mpi_t q;
50   unsigned int nbits;
51
52   l1 = gcry_sexp_find_token (key, "public-key", 0);
53   if (!l1)
54     return 0; /* Does not contain a key object.  */
55   l2 = gcry_sexp_cadr (l1);
56   gcry_sexp_release  (l1);
57   l1 = gcry_sexp_find_token (l2, "q", 1);
58   gcry_sexp_release (l2);
59   if (!l1)
60     return 0; /* Invalid object.  */
61   q = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG);
62   gcry_sexp_release (l1);
63   if (!q)
64     return 0; /* Missing value.  */
65   nbits = gcry_mpi_get_nbits (q);
66   gcry_mpi_release (q);
67
68   return nbits;
69 }
70
71
72 static int
73 do_encode_md (gcry_md_hd_t md, int algo, int pkalgo, unsigned int nbits,
74               gcry_sexp_t pkey, gcry_mpi_t *r_val)
75 {
76   int n;
77   size_t nframe;
78   unsigned char *frame;
79
80   if (pkalgo == GCRY_PK_DSA || pkalgo == MY_GCRY_PK_ECDSA)
81     {
82       unsigned int qbits;
83
84       if ( pkalgo == MY_GCRY_PK_ECDSA )
85         qbits = gcry_pk_get_nbits (pkey);
86       else
87         qbits = get_dsa_qbits (pkey);
88
89       if ( (qbits%8) )
90         {
91           log_error(_("DSA requires the hash length to be a"
92                       " multiple of 8 bits\n"));
93           return gpg_error (GPG_ERR_INTERNAL);
94         }
95
96       /* Don't allow any Q smaller than 160 bits.  We don't want
97          someone to issue signatures from a key with a 16-bit Q or
98          something like that, which would look correct but allow
99          trivial forgeries.  Yes, I know this rules out using MD5 with
100          DSA. ;) */
101       if (qbits < 160)
102         {
103           log_error (_("%s key uses an unsafe (%u bit) hash\n"),
104                      gcry_pk_algo_name (pkalgo), qbits);
105           return gpg_error (GPG_ERR_INTERNAL);
106         }
107
108       /* Check if we're too short.  Too long is safe as we'll
109          automatically left-truncate. */
110       nframe = gcry_md_get_algo_dlen (algo);
111       if (nframe < qbits/8)
112         {
113           log_error (_("a %u bit hash is not valid for a %u bit %s key\n"),
114                      (unsigned int)nframe*8,
115                      gcry_pk_get_nbits (pkey), 
116                      gcry_pk_algo_name (pkalgo));
117           /* FIXME: we need to check the requirements for ECDSA.  */
118           if (nframe < 20 || pkalgo == GCRY_PK_DSA  )
119             return gpg_error (GPG_ERR_INTERNAL);
120         }
121
122       frame = xtrymalloc (nframe);
123       if (!frame)
124         return out_of_core ();
125       memcpy (frame, gcry_md_read (md, algo), nframe);
126       n = nframe;
127       /* Truncate.  */
128       if (n > qbits/8)
129         n = qbits/8;
130     }
131   else
132     {
133       int i;
134       unsigned char asn[100];
135       size_t asnlen;
136       size_t len;
137
138       nframe = (nbits+7) / 8;
139
140       asnlen = DIM(asn);
141       if (!algo || gcry_md_test_algo (algo))
142         return gpg_error (GPG_ERR_DIGEST_ALGO);
143       if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
144         {
145           log_error ("no object identifier for algo %d\n", algo);
146           return gpg_error (GPG_ERR_INTERNAL);
147         }
148       
149       len = gcry_md_get_algo_dlen (algo);
150       
151       if ( len + asnlen + 4  > nframe )
152         {
153           log_error ("can't encode a %d bit MD into a %d bits frame\n",
154                      (int)(len*8), (int)nbits);
155           return gpg_error (GPG_ERR_INTERNAL);
156         }
157       
158       /* We encode the MD in this way:
159        *
160        *           0  A PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
161        *
162        * PAD consists of FF bytes.
163        */
164       frame = xtrymalloc (nframe);
165       if (!frame)
166         return out_of_core ();
167       n = 0;
168       frame[n++] = 0;
169       frame[n++] = 1; /* block type */
170       i = nframe - len - asnlen -3 ;
171       assert ( i > 1 );
172       memset ( frame+n, 0xff, i ); n += i;
173       frame[n++] = 0;
174       memcpy ( frame+n, asn, asnlen ); n += asnlen;
175       memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len;
176       assert ( n == nframe );
177     }
178   if (DBG_CRYPTO)
179     {
180       int j;
181       log_debug ("encoded hash:");
182       for (j=0; j < nframe; j++)
183         log_printf (" %02X", frame[j]);
184       log_printf ("\n");
185     }
186       
187   gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, n, &nframe);
188   xfree (frame);
189   return 0;
190 }
191
192 /* Return the public key algorithm id from the S-expression PKEY.
193    FIXME: libgcrypt should provide such a function.  Note that this
194    implementation uses the names as used by libksba.  */
195 static int
196 pk_algo_from_sexp (gcry_sexp_t pkey)
197 {
198   gcry_sexp_t l1, l2;
199   const char *name;
200   size_t n;
201   int algo;
202
203   l1 = gcry_sexp_find_token (pkey, "public-key", 0);
204   if (!l1)
205     return 0; /* Not found.  */
206   l2 = gcry_sexp_cadr (l1);
207   gcry_sexp_release (l1);
208
209   name = gcry_sexp_nth_data (l2, 0, &n);
210   if (!name)
211     algo = 0; /* Not found. */
212   else if (n==3 && !memcmp (name, "rsa", 3))
213     algo = GCRY_PK_RSA;
214   else if (n==3 && !memcmp (name, "dsa", 3))
215     algo = GCRY_PK_DSA;
216   /* Because this function is called only for verification we can
217      assume that ECC actually means ECDSA.  */
218   else if (n==3 && !memcmp (name, "ecc", 3))
219     algo = MY_GCRY_PK_ECDSA;
220   else if (n==13 && !memcmp (name, "ambiguous-rsa", 13))
221     algo = GCRY_PK_RSA;
222   else
223     algo = 0;
224   gcry_sexp_release (l2);
225   return algo;
226 }
227
228
229 /* Check the signature on CERT using the ISSUER-CERT.  This function
230    does only test the cryptographic signature and nothing else.  It is
231    assumed that the ISSUER_CERT is valid. */
232 int
233 gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
234 {
235   const char *algoid;
236   gcry_md_hd_t md;
237   int rc, algo;
238   gcry_mpi_t frame;
239   ksba_sexp_t p;
240   size_t n;
241   gcry_sexp_t s_sig, s_hash, s_pkey;
242
243   algo = gcry_md_map_name ( (algoid=ksba_cert_get_digest_algo (cert)));
244   if (!algo)
245     {
246       log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?");
247       if (algoid
248           && (  !strcmp (algoid, "1.2.840.113549.1.1.2")
249                 ||!strcmp (algoid, "1.2.840.113549.2.2")))
250         log_info (_("(this is the MD2 algorithm)\n"));
251       return gpg_error (GPG_ERR_GENERAL);
252     }
253   rc = gcry_md_open (&md, algo, 0);
254   if (rc)
255     {
256       log_error ("md_open failed: %s\n", gpg_strerror (rc));
257       return rc;
258     }
259   if (DBG_HASHING)
260     gcry_md_start_debug (md, "hash.cert");
261
262   rc = ksba_cert_hash (cert, 1, HASH_FNC, md);
263   if (rc)
264     {
265       log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (rc));
266       gcry_md_close (md);
267       return rc;
268     }
269   gcry_md_final (md);
270
271   p = ksba_cert_get_sig_val (cert);
272   n = gcry_sexp_canon_len (p, 0, NULL, NULL);
273   if (!n)
274     {
275       log_error ("libksba did not return a proper S-Exp\n");
276       gcry_md_close (md);
277       ksba_free (p);
278       return gpg_error (GPG_ERR_BUG);
279     }
280   if (DBG_CRYPTO)
281     {
282       int j;
283       log_debug ("signature value:");
284       for (j=0; j < n; j++)
285         log_printf (" %02X", p[j]);
286       log_printf ("\n");
287     }
288
289   rc = gcry_sexp_sscan ( &s_sig, NULL, (char*)p, n);
290   ksba_free (p);
291   if (rc)
292     {
293       log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
294       gcry_md_close (md);
295       return rc;
296     }
297
298   p = ksba_cert_get_public_key (issuer_cert);
299   n = gcry_sexp_canon_len (p, 0, NULL, NULL);
300   if (!n)
301     {
302       log_error ("libksba did not return a proper S-Exp\n");
303       gcry_md_close (md);
304       ksba_free (p);
305       gcry_sexp_release (s_sig);
306       return gpg_error (GPG_ERR_BUG);
307     }
308   rc = gcry_sexp_sscan ( &s_pkey, NULL, (char*)p, n);
309   ksba_free (p);
310   if (rc)
311     {
312       log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
313       gcry_md_close (md);
314       gcry_sexp_release (s_sig);
315       return rc;
316     }
317
318   rc = do_encode_md (md, algo, pk_algo_from_sexp (s_pkey),
319                      gcry_pk_get_nbits (s_pkey), s_pkey, &frame);
320   if (rc)
321     {
322       gcry_md_close (md);
323       gcry_sexp_release (s_sig);
324       gcry_sexp_release (s_pkey);
325       return rc;
326     }
327
328   /* put hash into the S-Exp s_hash */
329   if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
330     BUG ();
331   gcry_mpi_release (frame);
332
333   
334   rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
335   if (DBG_X509)
336       log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
337   gcry_md_close (md);
338   gcry_sexp_release (s_sig);
339   gcry_sexp_release (s_hash);
340   gcry_sexp_release (s_pkey);
341   return rc;
342 }
343
344
345
346 int
347 gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval,
348                            gcry_md_hd_t md, int algo)
349 {
350   int rc;
351   ksba_sexp_t p;
352   gcry_mpi_t frame;
353   gcry_sexp_t s_sig, s_hash, s_pkey;
354   size_t n;
355
356   n = gcry_sexp_canon_len (sigval, 0, NULL, NULL);
357   if (!n)
358     {
359       log_error ("libksba did not return a proper S-Exp\n");
360       return gpg_error (GPG_ERR_BUG);
361     }
362   rc = gcry_sexp_sscan (&s_sig, NULL, (char*)sigval, n);
363   if (rc)
364     {
365       log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
366       return rc;
367     }
368
369   p = ksba_cert_get_public_key (cert);
370   n = gcry_sexp_canon_len (p, 0, NULL, NULL);
371   if (!n)
372     {
373       log_error ("libksba did not return a proper S-Exp\n");
374       ksba_free (p);
375       gcry_sexp_release (s_sig);
376       return gpg_error (GPG_ERR_BUG);
377     }
378   if (DBG_CRYPTO)
379     log_printhex ("public key: ", p, n);
380
381   rc = gcry_sexp_sscan ( &s_pkey, NULL, (char*)p, n);
382   ksba_free (p);
383   if (rc)
384     {
385       log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
386       gcry_sexp_release (s_sig);
387       return rc;
388     }
389
390
391   rc = do_encode_md (md, algo, pk_algo_from_sexp (s_pkey),
392                      gcry_pk_get_nbits (s_pkey), s_pkey, &frame);
393   if (rc)
394     {
395       gcry_sexp_release (s_sig);
396       gcry_sexp_release (s_pkey);
397       return rc;
398     }
399   /* put hash into the S-Exp s_hash */
400   if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
401     BUG ();
402   gcry_mpi_release (frame);
403   
404   rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
405   if (DBG_X509)
406       log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
407   gcry_sexp_release (s_sig);
408   gcry_sexp_release (s_hash);
409   gcry_sexp_release (s_pkey);
410   return rc;
411 }
412
413
414
415 int
416 gpgsm_create_cms_signature (ctrl_t ctrl, ksba_cert_t cert,
417                             gcry_md_hd_t md, int mdalgo,
418                             unsigned char **r_sigval)
419 {
420   int rc;
421   char *grip, *desc;
422   size_t siglen;
423
424   grip = gpgsm_get_keygrip_hexstring (cert);
425   if (!grip)
426     return gpg_error (GPG_ERR_BAD_CERT);
427
428   desc = gpgsm_format_keydesc (cert);
429
430   rc = gpgsm_agent_pksign (ctrl, grip, desc, gcry_md_read(md, mdalgo), 
431                            gcry_md_get_algo_dlen (mdalgo), mdalgo,
432                            r_sigval, &siglen);
433   xfree (desc);
434   xfree (grip);
435   return rc;
436 }
437
438
439