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 3 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, see <http://www.gnu.org/licenses/>.
37 /* Remove this if libgcrypt 1.3.0 is required. */
38 #define MY_GCRY_PK_ECDSA 301
41 /* Return the number of bits of the Q parameter from the DSA key
44 get_dsa_qbits (gcry_sexp_t key
)
50 l1
= gcry_sexp_find_token (key
, "public-key", 0);
52 return 0; /* Does not contain a key object. */
53 l2
= gcry_sexp_cadr (l1
);
54 gcry_sexp_release (l1
);
55 l1
= gcry_sexp_find_token (l2
, "q", 1);
56 gcry_sexp_release (l2
);
58 return 0; /* Invalid object. */
59 q
= gcry_sexp_nth_mpi (l1
, 1, GCRYMPI_FMT_USG
);
60 gcry_sexp_release (l1
);
62 return 0; /* Missing value. */
63 nbits
= gcry_mpi_get_nbits (q
);
71 do_encode_md (gcry_md_hd_t md
, int algo
, int pkalgo
, unsigned int nbits
,
72 gcry_sexp_t pkey
, gcry_mpi_t
*r_val
)
78 if (pkalgo
== GCRY_PK_DSA
|| pkalgo
== MY_GCRY_PK_ECDSA
)
82 if ( pkalgo
== MY_GCRY_PK_ECDSA
)
83 qbits
= gcry_pk_get_nbits (pkey
);
85 qbits
= get_dsa_qbits (pkey
);
89 log_error(_("DSA requires the hash length to be a"
90 " multiple of 8 bits\n"));
91 return gpg_error (GPG_ERR_INTERNAL
);
94 /* Don't allow any Q smaller than 160 bits. We don't want
95 someone to issue signatures from a key with a 16-bit Q or
96 something like that, which would look correct but allow
97 trivial forgeries. Yes, I know this rules out using MD5 with
101 log_error (_("%s key uses an unsafe (%u bit) hash\n"),
102 gcry_pk_algo_name (pkalgo
), qbits
);
103 return gpg_error (GPG_ERR_INTERNAL
);
106 /* Check if we're too short. Too long is safe as we'll
107 automatically left-truncate. */
108 nframe
= gcry_md_get_algo_dlen (algo
);
109 if (nframe
< qbits
/8)
111 log_error (_("a %u bit hash is not valid for a %u bit %s key\n"),
112 (unsigned int)nframe
*8,
113 gcry_pk_get_nbits (pkey
),
114 gcry_pk_algo_name (pkalgo
));
115 /* FIXME: we need to check the requirements for ECDSA. */
116 if (nframe
< 20 || pkalgo
== GCRY_PK_DSA
)
117 return gpg_error (GPG_ERR_INTERNAL
);
120 frame
= xtrymalloc (nframe
);
122 return out_of_core ();
123 memcpy (frame
, gcry_md_read (md
, algo
), nframe
);
132 unsigned char asn
[100];
136 nframe
= (nbits
+7) / 8;
139 if (!algo
|| gcry_md_test_algo (algo
))
140 return gpg_error (GPG_ERR_DIGEST_ALGO
);
141 if (gcry_md_algo_info (algo
, GCRYCTL_GET_ASNOID
, asn
, &asnlen
))
143 log_error ("no object identifier for algo %d\n", algo
);
144 return gpg_error (GPG_ERR_INTERNAL
);
147 len
= gcry_md_get_algo_dlen (algo
);
149 if ( len
+ asnlen
+ 4 > nframe
)
151 log_error ("can't encode a %d bit MD into a %d bits frame\n",
152 (int)(len
*8), (int)nbits
);
153 return gpg_error (GPG_ERR_INTERNAL
);
156 /* We encode the MD in this way:
158 * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
160 * PAD consists of FF bytes.
162 frame
= xtrymalloc (nframe
);
164 return out_of_core ();
167 frame
[n
++] = 1; /* block type */
168 i
= nframe
- len
- asnlen
-3 ;
170 memset ( frame
+n
, 0xff, i
); n
+= i
;
172 memcpy ( frame
+n
, asn
, asnlen
); n
+= asnlen
;
173 memcpy ( frame
+n
, gcry_md_read(md
, algo
), len
); n
+= len
;
174 assert ( n
== nframe
);
179 log_debug ("encoded hash:");
180 for (j
=0; j
< nframe
; j
++)
181 log_printf (" %02X", frame
[j
]);
185 gcry_mpi_scan (r_val
, GCRYMPI_FMT_USG
, frame
, n
, &nframe
);
190 /* Return the public key algorithm id from the S-expression PKEY.
191 FIXME: libgcrypt should provide such a function. Note that this
192 implementation uses the names as used by libksba. */
194 pk_algo_from_sexp (gcry_sexp_t pkey
)
201 l1
= gcry_sexp_find_token (pkey
, "public-key", 0);
203 return 0; /* Not found. */
204 l2
= gcry_sexp_cadr (l1
);
205 gcry_sexp_release (l1
);
207 name
= gcry_sexp_nth_data (l2
, 0, &n
);
209 algo
= 0; /* Not found. */
210 else if (n
==3 && !memcmp (name
, "rsa", 3))
212 else if (n
==3 && !memcmp (name
, "dsa", 3))
214 /* Because this function is called only for verification we can
215 assume that ECC actually means ECDSA. */
216 else if (n
==3 && !memcmp (name
, "ecc", 3))
217 algo
= MY_GCRY_PK_ECDSA
;
218 else if (n
==13 && !memcmp (name
, "ambiguous-rsa", 13))
222 gcry_sexp_release (l2
);
227 /* Check the signature on CERT using the ISSUER-CERT. This function
228 does only test the cryptographic signature and nothing else. It is
229 assumed that the ISSUER_CERT is valid. */
231 gpgsm_check_cert_sig (ksba_cert_t issuer_cert
, ksba_cert_t cert
)
239 gcry_sexp_t s_sig
, s_hash
, s_pkey
;
241 algo
= gcry_md_map_name ( (algoid
=ksba_cert_get_digest_algo (cert
)));
244 log_error ("unknown hash algorithm `%s'\n", algoid
? algoid
:"?");
246 && ( !strcmp (algoid
, "1.2.840.113549.1.1.2")
247 ||!strcmp (algoid
, "1.2.840.113549.2.2")))
248 log_info (_("(this is the MD2 algorithm)\n"));
249 return gpg_error (GPG_ERR_GENERAL
);
251 rc
= gcry_md_open (&md
, algo
, 0);
254 log_error ("md_open failed: %s\n", gpg_strerror (rc
));
258 gcry_md_start_debug (md
, "hash.cert");
260 rc
= ksba_cert_hash (cert
, 1, HASH_FNC
, md
);
263 log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (rc
));
269 p
= ksba_cert_get_sig_val (cert
);
270 n
= gcry_sexp_canon_len (p
, 0, NULL
, NULL
);
273 log_error ("libksba did not return a proper S-Exp\n");
276 return gpg_error (GPG_ERR_BUG
);
281 log_debug ("signature value:");
282 for (j
=0; j
< n
; j
++)
283 log_printf (" %02X", p
[j
]);
287 rc
= gcry_sexp_sscan ( &s_sig
, NULL
, (char*)p
, n
);
291 log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc
));
296 p
= ksba_cert_get_public_key (issuer_cert
);
297 n
= gcry_sexp_canon_len (p
, 0, NULL
, NULL
);
300 log_error ("libksba did not return a proper S-Exp\n");
303 gcry_sexp_release (s_sig
);
304 return gpg_error (GPG_ERR_BUG
);
306 rc
= gcry_sexp_sscan ( &s_pkey
, NULL
, (char*)p
, n
);
310 log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc
));
312 gcry_sexp_release (s_sig
);
316 rc
= do_encode_md (md
, algo
, pk_algo_from_sexp (s_pkey
),
317 gcry_pk_get_nbits (s_pkey
), s_pkey
, &frame
);
321 gcry_sexp_release (s_sig
);
322 gcry_sexp_release (s_pkey
);
326 /* put hash into the S-Exp s_hash */
327 if ( gcry_sexp_build (&s_hash
, NULL
, "%m", frame
) )
329 gcry_mpi_release (frame
);
332 rc
= gcry_pk_verify (s_sig
, s_hash
, s_pkey
);
334 log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc
));
336 gcry_sexp_release (s_sig
);
337 gcry_sexp_release (s_hash
);
338 gcry_sexp_release (s_pkey
);
345 gpgsm_check_cms_signature (ksba_cert_t cert
, ksba_const_sexp_t sigval
,
346 gcry_md_hd_t md
, int mdalgo
, int *r_pkalgo
)
351 gcry_sexp_t s_sig
, s_hash
, s_pkey
;
358 n
= gcry_sexp_canon_len (sigval
, 0, NULL
, NULL
);
361 log_error ("libksba did not return a proper S-Exp\n");
362 return gpg_error (GPG_ERR_BUG
);
364 rc
= gcry_sexp_sscan (&s_sig
, NULL
, (char*)sigval
, n
);
367 log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc
));
371 p
= ksba_cert_get_public_key (cert
);
372 n
= gcry_sexp_canon_len (p
, 0, NULL
, NULL
);
375 log_error ("libksba did not return a proper S-Exp\n");
377 gcry_sexp_release (s_sig
);
378 return gpg_error (GPG_ERR_BUG
);
381 log_printhex ("public key: ", p
, n
);
383 rc
= gcry_sexp_sscan ( &s_pkey
, NULL
, (char*)p
, n
);
387 log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc
));
388 gcry_sexp_release (s_sig
);
392 pkalgo
= pk_algo_from_sexp (s_pkey
);
395 rc
= do_encode_md (md
, mdalgo
, pkalgo
,
396 gcry_pk_get_nbits (s_pkey
), s_pkey
, &frame
);
399 gcry_sexp_release (s_sig
);
400 gcry_sexp_release (s_pkey
);
403 /* put hash into the S-Exp s_hash */
404 if ( gcry_sexp_build (&s_hash
, NULL
, "%m", frame
) )
406 gcry_mpi_release (frame
);
408 rc
= gcry_pk_verify (s_sig
, s_hash
, s_pkey
);
410 log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc
));
411 gcry_sexp_release (s_sig
);
412 gcry_sexp_release (s_hash
);
413 gcry_sexp_release (s_pkey
);
420 gpgsm_create_cms_signature (ctrl_t ctrl
, ksba_cert_t cert
,
421 gcry_md_hd_t md
, int mdalgo
,
422 unsigned char **r_sigval
)
428 grip
= gpgsm_get_keygrip_hexstring (cert
);
430 return gpg_error (GPG_ERR_BAD_CERT
);
432 desc
= gpgsm_format_keydesc (cert
);
434 rc
= gpgsm_agent_pksign (ctrl
, grip
, desc
, gcry_md_read(md
, mdalgo
),
435 gcry_md_get_algo_dlen (mdalgo
), mdalgo
,