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