2005-04-15 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / sm / certcheck.c
blob611d3219c8a749a53c78de059c888f65e60e6d04
1 /* certcheck.c - check one certificate
2 * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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
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>
30 #include "gpgsm.h"
31 #include <gcrypt.h>
32 #include <ksba.h>
34 #include "keydb.h"
35 #include "i18n.h"
38 static int
39 do_encode_md (gcry_md_hd_t md, int algo, int pkalgo, unsigned int nbits,
40 gcry_mpi_t *r_val)
42 int n, nframe;
43 unsigned char *frame;
45 if (pkalgo == GCRY_PK_DSA)
47 nframe = gcry_md_get_algo_dlen (algo);
48 if (nframe != 20)
50 log_error (_("DSA requires the use of a 160 bit hash algorithm\n"));
51 return gpg_error (GPG_ERR_INTERNAL);
53 frame = xtrymalloc (nframe);
54 if (!frame)
55 return OUT_OF_CORE (errno);
56 memcpy (frame, gcry_md_read (md, algo), nframe);
57 n = nframe;
59 else
61 int i;
62 unsigned char asn[100];
63 size_t asnlen;
64 size_t len;
66 nframe = (nbits+7) / 8;
68 asnlen = DIM(asn);
69 if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
71 log_error ("no object identifier for algo %d\n", algo);
72 return gpg_error (GPG_ERR_INTERNAL);
75 len = gcry_md_get_algo_dlen (algo);
77 if ( len + asnlen + 4 > nframe )
79 log_error ("can't encode a %d bit MD into a %d bits frame\n",
80 (int)(len*8), (int)nbits);
81 return gpg_error (GPG_ERR_INTERNAL);
84 /* We encode the MD in this way:
86 * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
88 * PAD consists of FF bytes.
90 frame = xtrymalloc (nframe);
91 if (!frame)
92 return OUT_OF_CORE (errno);
93 n = 0;
94 frame[n++] = 0;
95 frame[n++] = 1; /* block type */
96 i = nframe - len - asnlen -3 ;
97 assert ( i > 1 );
98 memset ( frame+n, 0xff, i ); n += i;
99 frame[n++] = 0;
100 memcpy ( frame+n, asn, asnlen ); n += asnlen;
101 memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len;
102 assert ( n == nframe );
104 if (DBG_CRYPTO)
106 int j;
107 log_debug ("encoded hash:");
108 for (j=0; j < nframe; j++)
109 log_printf (" %02X", frame[j]);
110 log_printf ("\n");
113 gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, n, &nframe);
114 xfree (frame);
115 return 0;
118 /* Return the public key algorithm id from the S-expression PKEY.
119 FIXME: libgcrypt should provide such a function. Note that this
120 implementation uses the names as used by libksba. */
121 static int
122 pk_algo_from_sexp (gcry_sexp_t pkey)
124 gcry_sexp_t l1, l2;
125 const char *name;
126 size_t n;
127 int algo;
129 l1 = gcry_sexp_find_token (pkey, "public-key", 0);
130 if (!l1)
131 return 0; /* Not found. */
132 l2 = gcry_sexp_cadr (l1);
133 gcry_sexp_release (l1);
135 name = gcry_sexp_nth_data (l2, 0, &n);
136 if (!name)
137 algo = 0; /* Not found. */
138 else if (n==3 && !memcmp (name, "rsa", 3))
139 algo = GCRY_PK_RSA;
140 else if (n==3 && !memcmp (name, "dsa", 3))
141 algo = GCRY_PK_DSA;
142 else if (n==13 && !memcmp (name, "ambiguous-rsa", 13))
143 algo = GCRY_PK_RSA;
144 else
145 algo = 0;
146 gcry_sexp_release (l2);
147 return algo;
152 Check the signature on CERT using the ISSUER-CERT. This function
153 does only test the cryptographic signature and nothing else. It is
154 assumed that the ISSUER_CERT is valid. */
156 gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
158 const char *algoid;
159 gcry_md_hd_t md;
160 int rc, algo;
161 gcry_mpi_t frame;
162 ksba_sexp_t p;
163 size_t n;
164 gcry_sexp_t s_sig, s_hash, s_pkey;
166 algo = gcry_md_map_name ( (algoid=ksba_cert_get_digest_algo (cert)));
167 if (!algo)
169 log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?");
170 return gpg_error (GPG_ERR_GENERAL);
172 rc = gcry_md_open (&md, algo, 0);
173 if (rc)
175 log_error ("md_open failed: %s\n", gpg_strerror (rc));
176 return rc;
178 if (DBG_HASHING)
179 gcry_md_start_debug (md, "hash.cert");
181 rc = ksba_cert_hash (cert, 1, HASH_FNC, md);
182 if (rc)
184 log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (rc));
185 gcry_md_close (md);
186 return rc;
188 gcry_md_final (md);
190 p = ksba_cert_get_sig_val (cert);
191 n = gcry_sexp_canon_len (p, 0, NULL, NULL);
192 if (!n)
194 log_error ("libksba did not return a proper S-Exp\n");
195 gcry_md_close (md);
196 ksba_free (p);
197 return gpg_error (GPG_ERR_BUG);
199 if (DBG_CRYPTO)
201 int j;
202 log_debug ("signature value:");
203 for (j=0; j < n; j++)
204 log_printf (" %02X", p[j]);
205 log_printf ("\n");
208 rc = gcry_sexp_sscan ( &s_sig, NULL, p, n);
209 ksba_free (p);
210 if (rc)
212 log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
213 gcry_md_close (md);
214 return rc;
217 p = ksba_cert_get_public_key (issuer_cert);
218 n = gcry_sexp_canon_len (p, 0, NULL, NULL);
219 if (!n)
221 log_error ("libksba did not return a proper S-Exp\n");
222 gcry_md_close (md);
223 ksba_free (p);
224 gcry_sexp_release (s_sig);
225 return gpg_error (GPG_ERR_BUG);
227 rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
228 ksba_free (p);
229 if (rc)
231 log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
232 gcry_md_close (md);
233 gcry_sexp_release (s_sig);
234 return rc;
237 rc = do_encode_md (md, algo, pk_algo_from_sexp (s_pkey),
238 gcry_pk_get_nbits (s_pkey), &frame);
239 if (rc)
241 gcry_md_close (md);
242 gcry_sexp_release (s_sig);
243 gcry_sexp_release (s_pkey);
244 return rc;
247 /* put hash into the S-Exp s_hash */
248 if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
249 BUG ();
250 gcry_mpi_release (frame);
253 rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
254 if (DBG_X509)
255 log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
256 gcry_md_close (md);
257 gcry_sexp_release (s_sig);
258 gcry_sexp_release (s_hash);
259 gcry_sexp_release (s_pkey);
260 return rc;
266 gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval,
267 gcry_md_hd_t md, int algo)
269 int rc;
270 ksba_sexp_t p;
271 gcry_mpi_t frame;
272 gcry_sexp_t s_sig, s_hash, s_pkey;
273 size_t n;
275 n = gcry_sexp_canon_len (sigval, 0, NULL, NULL);
276 if (!n)
278 log_error ("libksba did not return a proper S-Exp\n");
279 return gpg_error (GPG_ERR_BUG);
281 rc = gcry_sexp_sscan (&s_sig, NULL, sigval, n);
282 if (rc)
284 log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
285 return rc;
288 p = ksba_cert_get_public_key (cert);
289 n = gcry_sexp_canon_len (p, 0, NULL, NULL);
290 if (!n)
292 log_error ("libksba did not return a proper S-Exp\n");
293 ksba_free (p);
294 gcry_sexp_release (s_sig);
295 return gpg_error (GPG_ERR_BUG);
297 if (DBG_CRYPTO)
298 log_printhex ("public key: ", p, n);
300 rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
301 ksba_free (p);
302 if (rc)
304 log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc));
305 gcry_sexp_release (s_sig);
306 return rc;
310 rc = do_encode_md (md, algo, pk_algo_from_sexp (s_pkey),
311 gcry_pk_get_nbits (s_pkey), &frame);
312 if (rc)
314 gcry_sexp_release (s_sig);
315 gcry_sexp_release (s_pkey);
316 return rc;
318 /* put hash into the S-Exp s_hash */
319 if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
320 BUG ();
321 gcry_mpi_release (frame);
323 rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
324 if (DBG_X509)
325 log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
326 gcry_sexp_release (s_sig);
327 gcry_sexp_release (s_hash);
328 gcry_sexp_release (s_pkey);
329 return rc;
335 gpgsm_create_cms_signature (ctrl_t ctrl, ksba_cert_t cert,
336 gcry_md_hd_t md, int mdalgo, char **r_sigval)
338 int rc;
339 char *grip, *desc;
340 size_t siglen;
342 grip = gpgsm_get_keygrip_hexstring (cert);
343 if (!grip)
344 return gpg_error (GPG_ERR_BAD_CERT);
346 desc = gpgsm_format_keydesc (cert);
348 rc = gpgsm_agent_pksign (ctrl, grip, desc, gcry_md_read(md, mdalgo),
349 gcry_md_get_algo_dlen (mdalgo), mdalgo,
350 r_sigval, &siglen);
351 xfree (desc);
352 xfree (grip);
353 return rc;