Line data Source code
1 : /* cert-basic.c - basic test for the certificate management.
2 : * Copyright (C) 2001, 2002, 2004, 2005 g10 Code GmbH
3 : *
4 : * This file is part of KSBA.
5 : *
6 : * KSBA 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 : * KSBA 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 <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include <stdio.h>
21 : #include <stdlib.h>
22 : #include <string.h>
23 : #include <assert.h>
24 : #include <errno.h>
25 :
26 : #include "../src/ksba.h"
27 : #define _KSBA_VISIBILITY_DEFAULT /* */
28 : #include "../src/keyinfo.h"
29 :
30 : #include "oidtranstbl.h"
31 : #include "t-common.h"
32 :
33 : #ifdef __MINGW32CE__
34 : #define getenv(a) (NULL)
35 : #endif
36 :
37 : #define digitp(p) (*(p) >= '0' && *(p) <= '9')
38 :
39 : #define fail_if_err(a) do { if(a) { \
40 : fprintf (stderr, "%s:%d: KSBA error: %s\n", \
41 : __FILE__, __LINE__, gpg_strerror(a)); \
42 : exit (1); } \
43 : } while(0)
44 :
45 :
46 : #define fail_if_err2(f, a) do { if(a) {\
47 : fprintf (stderr, "%s:%d: KSBA error on file `%s': %s\n", \
48 : __FILE__, __LINE__, (f), gpg_strerror(a)); \
49 : exit (1); } \
50 : } while(0)
51 :
52 : #define xfree(a) ksba_free (a)
53 :
54 : static int verbose;
55 : static int errorcount = 0;
56 :
57 :
58 : static void
59 5 : print_names (int indent, ksba_name_t name)
60 : {
61 : int idx;
62 : const char *s;
63 : int indent_all;
64 :
65 5 : if ((indent_all = (indent < 0)))
66 0 : indent = - indent;
67 :
68 5 : if (!name)
69 : {
70 2 : fputs ("none\n", stdout);
71 2 : return;
72 : }
73 :
74 6 : for (idx=0; (s = ksba_name_enum (name, idx)); idx++)
75 : {
76 3 : char *p = ksba_name_get_uri (name, idx);
77 3 : printf ("%*s%s\n", idx||indent_all?indent:0, "", p?p:s);
78 3 : xfree (p);
79 : }
80 : }
81 :
82 :
83 : /* Return the description for OID; if no description is available
84 : NULL is returned. */
85 : static const char *
86 23 : get_oid_desc (const char *oid)
87 : {
88 : int i;
89 :
90 23 : if (oid)
91 40112 : for (i=0; oidtranstbl[i].oid; i++)
92 40112 : if (!strcmp (oidtranstbl[i].oid, oid))
93 23 : return oidtranstbl[i].desc;
94 0 : return NULL;
95 : }
96 :
97 :
98 : static void
99 0 : print_oid_and_desc (const char *oid, int with_lf)
100 : {
101 0 : const char *s = get_oid_desc (oid);
102 0 : printf ("%s%s%s%s",
103 : oid, s?" (":"", s?s:"", s?")":"");
104 0 : if (with_lf)
105 0 : putchar ('\n');
106 0 : }
107 :
108 :
109 : static void
110 0 : print_oid_list (int indent, char *list)
111 : {
112 : char *lf;
113 : int indent_all, c;
114 : size_t n;
115 :
116 0 : if ((indent_all = (indent < 0)))
117 0 : indent = - indent;
118 :
119 0 : while (*list)
120 : {
121 0 : printf ("%*s", indent_all?indent:0, "");
122 0 : indent_all = 1;
123 :
124 0 : if (!(lf = strchr (list, '\n')))
125 0 : lf = list + strlen (list);
126 :
127 0 : n = strspn (list, "0123456789.");
128 0 : c = list[n];
129 0 : list[n] = 0;
130 0 : print_oid_and_desc (list, 0);
131 0 : list[n] = c;
132 :
133 0 : c = *lf;
134 0 : *lf = 0;
135 0 : printf (" %s\n", list+n);
136 0 : *lf = c;
137 0 : list = *lf? (lf+1):lf;
138 : }
139 0 : }
140 :
141 :
142 :
143 :
144 : static void
145 3 : list_extensions (ksba_cert_t cert)
146 : {
147 : gpg_error_t err;
148 : const char *oid;
149 : int idx, crit, is_ca, pathlen;
150 : size_t off, len;
151 : unsigned int usage, reason;
152 : char *string, *p;
153 : ksba_name_t name1, name2;
154 : ksba_sexp_t serial;
155 : ksba_sexp_t keyid;
156 :
157 26 : for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
158 20 : &oid, &crit, &off, &len));idx++)
159 : {
160 20 : const char *s = get_oid_desc (oid);
161 20 : printf ("Extn: %s%s%s%s at %d with length %d %s\n",
162 : oid, s?" (":"", s?s:"", s?")":"",
163 20 : (int)off, (int)len, crit? "(critical)":"");
164 : }
165 3 : if (err && gpg_err_code (err) != GPG_ERR_EOF )
166 : {
167 0 : fprintf (stderr,
168 : "%s:%d: enumerating extensions failed: %s\n",
169 : __FILE__, __LINE__, gpg_strerror (err));
170 0 : errorcount++;
171 : }
172 :
173 : /* subjectKeyIdentifier */
174 3 : err = ksba_cert_get_subj_key_id (cert, NULL, &keyid);
175 3 : if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA)
176 : {
177 3 : fputs ("SubjectKeyIdentifier: ", stdout);
178 3 : if (gpg_err_code (err) == GPG_ERR_NO_DATA)
179 1 : fputs ("none", stdout);
180 : else
181 : {
182 2 : print_sexp (keyid);
183 2 : ksba_free (keyid);
184 : }
185 3 : putchar ('\n');
186 : }
187 :
188 :
189 : /* authorityKeyIdentifier */
190 3 : err = ksba_cert_get_auth_key_id (cert, &keyid, &name1, &serial);
191 3 : if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA)
192 : {
193 3 : fputs ("AuthorityKeyIdentifier: ", stdout);
194 6 : if (gpg_err_code (err) == GPG_ERR_NO_DATA)
195 2 : fputs ("none\n", stdout);
196 : else
197 : {
198 1 : if (name1)
199 : {
200 1 : print_names (24, name1);
201 1 : ksba_name_release (name1);
202 1 : fputs (" serial: ", stdout);
203 1 : print_sexp (serial);
204 1 : ksba_free (serial);
205 : }
206 1 : putchar ('\n');
207 1 : if (keyid)
208 : {
209 1 : fputs (" keyIdentifier: ", stdout);
210 1 : print_sexp (keyid);
211 1 : ksba_free (keyid);
212 1 : putchar ('\n');
213 : }
214 : }
215 : }
216 : else
217 : {
218 0 : fprintf (stderr, "%s:%d: ksba_cert_get_auth_key_id: %s\n",
219 : __FILE__, __LINE__, gpg_strerror (err));
220 0 : errorcount++;
221 : }
222 :
223 3 : err = ksba_cert_is_ca (cert, &is_ca, &pathlen);
224 3 : if (err)
225 : {
226 0 : fprintf (stderr, "%s:%d: ksba_cert_is_ca failed: %s\n",
227 : __FILE__, __LINE__, gpg_strerror (err));
228 0 : errorcount++;
229 : }
230 3 : else if (is_ca)
231 3 : printf ("This is a CA certificate with a path length of %d\n", pathlen);
232 :
233 3 : err = ksba_cert_get_key_usage (cert, &usage);
234 3 : if (gpg_err_code (err) == GPG_ERR_NO_DATA)
235 1 : printf ("KeyUsage: Not specified\n");
236 2 : else if (err)
237 : {
238 0 : fprintf (stderr, "%s:%d: ksba_cert_get_key_usage failed: %s\n",
239 : __FILE__, __LINE__, gpg_strerror (err));
240 0 : errorcount++;
241 : }
242 : else
243 : {
244 2 : fputs ("KeyUsage:", stdout);
245 2 : if ( (usage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
246 0 : fputs (" digitalSignature", stdout);
247 2 : if ( (usage & KSBA_KEYUSAGE_NON_REPUDIATION))
248 0 : fputs (" nonRepudiation", stdout);
249 2 : if ( (usage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT))
250 0 : fputs (" keyEncipherment", stdout);
251 2 : if ( (usage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
252 0 : fputs (" dataEncripherment", stdout);
253 2 : if ( (usage & KSBA_KEYUSAGE_KEY_AGREEMENT))
254 0 : fputs (" keyAgreement", stdout);
255 2 : if ( (usage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
256 2 : fputs (" certSign", stdout);
257 2 : if ( (usage & KSBA_KEYUSAGE_CRL_SIGN))
258 2 : fputs (" crlSign", stdout);
259 2 : if ( (usage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
260 0 : fputs (" encipherOnly", stdout);
261 2 : if ( (usage & KSBA_KEYUSAGE_DECIPHER_ONLY))
262 0 : fputs (" decipherOnly", stdout);
263 2 : putchar ('\n');
264 : }
265 3 : err = ksba_cert_get_ext_key_usages (cert, &string);
266 3 : if (gpg_err_code (err) == GPG_ERR_NO_DATA)
267 3 : printf ("ExtKeyUsages: none\n");
268 0 : else if (err)
269 : {
270 0 : fprintf (stderr, "%s:%d: ksba_cert_ext_key_usages failed: %s\n",
271 : __FILE__, __LINE__, gpg_strerror (err));
272 0 : errorcount++;
273 : }
274 : else
275 : {
276 0 : fputs ("ExtKeyUsages: ", stdout);
277 0 : print_oid_list (14, string);
278 0 : xfree (string);
279 : }
280 :
281 :
282 3 : err = ksba_cert_get_cert_policies (cert, &string);
283 3 : if (gpg_err_code (err) == GPG_ERR_NO_DATA)
284 3 : printf ("CertificatePolicies: none\n");
285 0 : else if (err)
286 : {
287 0 : fprintf (stderr, "%s:%d: ksba_cert_get_cert_policies failed: %s\n",
288 : __FILE__, __LINE__, gpg_strerror (err));
289 0 : errorcount++;
290 : }
291 : else
292 : {
293 : /* for display purposes we replace the linefeeds by commas */
294 0 : for (p=string; *p; p++)
295 : {
296 0 : if (*p == '\n')
297 0 : *p = ',';
298 : }
299 0 : fputs ("CertificatePolicies: ", stdout);
300 0 : print_oid_list (21, string);
301 0 : xfree (string);
302 : }
303 :
304 : /* CRL distribution point */
305 8 : for (idx=0; !(err=ksba_cert_get_crl_dist_point (cert, idx,
306 : &name1, &name2,
307 2 : &reason));idx++)
308 : {
309 2 : fputs ("CRLDistPoint: ", stdout);
310 2 : print_names (14, name1);
311 2 : fputs (" reasons:", stdout);
312 2 : if ( !reason )
313 2 : fputs (" none", stdout);
314 2 : if ( (reason & KSBA_CRLREASON_UNSPECIFIED))
315 0 : fputs (" unused", stdout);
316 2 : if ( (reason & KSBA_CRLREASON_KEY_COMPROMISE))
317 0 : fputs (" keyCompromise", stdout);
318 2 : if ( (reason & KSBA_CRLREASON_CA_COMPROMISE))
319 0 : fputs (" caCompromise", stdout);
320 2 : if ( (reason & KSBA_CRLREASON_AFFILIATION_CHANGED))
321 0 : fputs (" affiliationChanged", stdout);
322 2 : if ( (reason & KSBA_CRLREASON_SUPERSEDED))
323 0 : fputs (" superseded", stdout);
324 2 : if ( (reason & KSBA_CRLREASON_CESSATION_OF_OPERATION))
325 0 : fputs (" cessationOfOperation", stdout);
326 2 : if ( (reason & KSBA_CRLREASON_CERTIFICATE_HOLD))
327 0 : fputs (" certificateHold", stdout);
328 2 : putchar ('\n');
329 2 : fputs (" issuer: ", stdout);
330 2 : print_names (14, name2);
331 2 : ksba_name_release (name1);
332 2 : ksba_name_release (name2);
333 : }
334 3 : if (err && gpg_err_code (err) != GPG_ERR_EOF)
335 : {
336 0 : fprintf (stderr, "%s:%d: ksba_cert_get_crl_dist_point failed: %s\n",
337 : __FILE__, __LINE__, gpg_strerror (err));
338 0 : errorcount++;
339 : }
340 :
341 : /* authorityInfoAccess. */
342 6 : for (idx=0; !(err=ksba_cert_get_authority_info_access (cert, idx,
343 : &string, &name1))
344 0 : ; idx++)
345 : {
346 0 : fputs ("authorityInfoAccess: ", stdout);
347 0 : print_oid_and_desc (string, 1);
348 0 : print_names (-21, name1);
349 0 : ksba_name_release (name1);
350 0 : ksba_free (string);
351 : }
352 3 : if (err && gpg_err_code (err) != GPG_ERR_EOF)
353 : {
354 0 : fprintf (stderr, "%s:%d: "
355 : "ksba_cert_get_authority_info_access failed: %s\n",
356 : __FILE__, __LINE__, gpg_strerror (err));
357 0 : errorcount++;
358 : }
359 :
360 : /* subjectInfoAccess. */
361 6 : for (idx=0; !(err=ksba_cert_get_subject_info_access (cert, idx,
362 : &string, &name1))
363 0 : ; idx++)
364 : {
365 0 : fputs ("subjectInfoAccess: ", stdout);
366 0 : print_oid_and_desc (string, 1);
367 0 : print_names (-19, name1);
368 0 : ksba_name_release (name1);
369 0 : ksba_free (string);
370 : }
371 3 : if (err && gpg_err_code (err) != GPG_ERR_EOF)
372 : {
373 0 : fprintf (stderr, "%s:%d: "
374 : "ksba_cert_get_subject_info_access failed: %s\n",
375 : __FILE__, __LINE__, gpg_strerror (err));
376 0 : errorcount++;
377 : }
378 :
379 3 : }
380 :
381 :
382 : static void
383 3 : one_file (const char *fname)
384 : {
385 : gpg_error_t err;
386 : FILE *fp;
387 : ksba_reader_t r;
388 : ksba_cert_t cert;
389 : char *dn;
390 : ksba_isotime_t t;
391 : int idx;
392 : ksba_sexp_t sexp;
393 : const char *oid, *s;
394 :
395 3 : fp = fopen (fname, "rb");
396 3 : if (!fp)
397 : {
398 0 : fprintf (stderr, "%s:%d: can't open `%s': %s\n",
399 0 : __FILE__, __LINE__, fname, strerror (errno));
400 0 : exit (1);
401 : }
402 :
403 3 : err = ksba_reader_new (&r);
404 3 : if (err)
405 0 : fail_if_err (err);
406 3 : err = ksba_reader_set_file (r, fp);
407 3 : fail_if_err (err);
408 :
409 3 : err = ksba_cert_new (&cert);
410 3 : if (err)
411 0 : fail_if_err (err);
412 :
413 3 : err = ksba_cert_read_der (cert, r);
414 3 : fail_if_err2 (fname, err);
415 :
416 3 : printf ("Certificate in `%s':\n", fname);
417 :
418 3 : sexp = ksba_cert_get_serial (cert);
419 3 : fputs (" serial....: ", stdout);
420 3 : print_sexp (sexp);
421 3 : ksba_free (sexp);
422 3 : putchar ('\n');
423 :
424 6 : for (idx=0;(dn = ksba_cert_get_issuer (cert, idx));idx++)
425 : {
426 3 : fputs (idx?" aka: ":" issuer....: ", stdout);
427 3 : print_dn (dn);
428 3 : ksba_free (dn);
429 3 : putchar ('\n');
430 : }
431 :
432 6 : for (idx=0;(dn = ksba_cert_get_subject (cert, idx));idx++)
433 : {
434 3 : fputs (idx?" aka: ":" subject...: ", stdout);
435 3 : print_dn (dn);
436 3 : ksba_free (dn);
437 3 : putchar ('\n');
438 : }
439 :
440 3 : ksba_cert_get_validity (cert, 0, t);
441 3 : fputs (" notBefore.: ", stdout);
442 3 : print_time (t);
443 3 : putchar ('\n');
444 3 : ksba_cert_get_validity (cert, 1, t);
445 3 : fputs (" notAfter..: ", stdout);
446 3 : print_time (t);
447 3 : putchar ('\n');
448 :
449 3 : oid = ksba_cert_get_digest_algo (cert);
450 3 : s = get_oid_desc (oid);
451 3 : printf (" hash algo.: %s%s%s%s\n",
452 : oid?oid:"(null)", s?" (":"",s?s:"",s?")":"");
453 :
454 : /* Under Windows the _ksba_keyinfo_from_sexp are not exported. */
455 : #ifndef __WIN32
456 : /* check that the sexp to keyinfo conversion works */
457 : {
458 : ksba_sexp_t public;
459 :
460 3 : public = ksba_cert_get_public_key (cert);
461 3 : if (!public)
462 : {
463 0 : fprintf (stderr, "%s:%d: public key not found\n",
464 : __FILE__, __LINE__);
465 0 : errorcount++;
466 : }
467 : else
468 : {
469 : unsigned char *der;
470 : size_t derlen;
471 :
472 3 : if (verbose)
473 : {
474 0 : fputs (" pubkey....: ", stdout);
475 0 : print_sexp (public);
476 0 : putchar ('\n');
477 : }
478 :
479 3 : err = _ksba_keyinfo_from_sexp (public, &der, &derlen);
480 3 : if (err)
481 : {
482 0 : fprintf (stderr, "%s:%d: converting public key failed: %s\n",
483 : __FILE__, __LINE__, gpg_strerror (err));
484 0 : errorcount++;
485 : }
486 : else
487 : {
488 : ksba_sexp_t tmp;
489 :
490 3 : if (verbose)
491 : {
492 0 : fputs (" pubkey-DER: ", stdout);
493 0 : print_hex (der, derlen);
494 0 : putchar ('\n');
495 : }
496 3 : err = _ksba_keyinfo_to_sexp (der, derlen, &tmp);
497 3 : if (err)
498 : {
499 0 : fprintf (stderr,
500 : "%s:%d: re-converting public key failed: %s\n",
501 : __FILE__, __LINE__, gpg_strerror (err));
502 0 : errorcount++;
503 : }
504 : else
505 : {
506 : unsigned char *der2;
507 : size_t derlen2;
508 :
509 3 : err = _ksba_keyinfo_from_sexp (tmp, &der2, &derlen2);
510 3 : if (err)
511 : {
512 0 : fprintf (stderr, "%s:%d: re-re-converting "
513 : "public key failed: %s\n",
514 : __FILE__, __LINE__, gpg_strerror (err));
515 0 : errorcount++;
516 : }
517 3 : else if (derlen != derlen2 || memcmp (der, der2, derlen))
518 : {
519 0 : fprintf (stderr, "%s:%d: mismatch after "
520 : "re-re-converting public key\n",
521 : __FILE__, __LINE__);
522 0 : errorcount++;
523 0 : xfree (der2);
524 : } else {
525 : /* Don't leak memory if everything is ok. */
526 3 : xfree (der2);
527 : }
528 3 : xfree (tmp);
529 : }
530 3 : xfree (der);
531 : }
532 3 : ksba_free (public);
533 : }
534 : }
535 : #endif
536 :
537 3 : if (verbose)
538 : {
539 0 : sexp = ksba_cert_get_sig_val (cert);
540 0 : fputs (" sigval....: ", stdout);
541 0 : print_sexp (sexp);
542 0 : ksba_free (sexp);
543 0 : putchar ('\n');
544 : }
545 :
546 3 : list_extensions (cert);
547 :
548 3 : ksba_cert_release (cert);
549 3 : err = ksba_cert_new (&cert);
550 3 : if (err)
551 0 : fail_if_err (err);
552 :
553 3 : err = ksba_cert_read_der (cert, r);
554 3 : if (err && gpg_err_code (err) != GPG_ERR_EOF)
555 : {
556 0 : fprintf (stderr, "%s:%d: expected EOF but got: %s\n",
557 : __FILE__, __LINE__, gpg_strerror (err));
558 0 : errorcount++;
559 : }
560 :
561 3 : putchar ('\n');
562 3 : ksba_cert_release (cert);
563 3 : ksba_reader_release (r);
564 3 : fclose (fp);
565 3 : }
566 :
567 :
568 :
569 :
570 : int
571 1 : main (int argc, char **argv)
572 : {
573 1 : const char *srcdir = getenv ("srcdir");
574 :
575 1 : if (!srcdir)
576 0 : srcdir = ".";
577 :
578 1 : if (argc)
579 : {
580 1 : argc--; argv++;
581 : }
582 :
583 1 : if (argc && !strcmp (*argv, "--verbose"))
584 : {
585 0 : verbose = 1;
586 0 : argc--; argv++;
587 : }
588 :
589 :
590 1 : if (argc)
591 : {
592 0 : for (; argc; argc--, argv++)
593 0 : one_file (*argv);
594 : }
595 : else
596 : {
597 1 : const char *files[] = {
598 : "cert_dfn_pca01.der",
599 : "cert_dfn_pca15.der",
600 : "cert_g10code_test1.der",
601 : NULL
602 : };
603 : int idx;
604 :
605 4 : for (idx=0; files[idx]; idx++)
606 : {
607 : char *fname;
608 :
609 3 : fname = xmalloc (strlen (srcdir) + 1 + strlen (files[idx]) + 1);
610 3 : strcpy (fname, srcdir);
611 3 : strcat (fname, "/");
612 3 : strcat (fname, files[idx]);
613 3 : one_file (fname);
614 3 : ksba_free (fname);
615 : }
616 : }
617 :
618 1 : return !!errorcount;
619 : }
|