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