certtool/p11tool: avoid cast to function call
[gnutls:gnutls.git] / src / certtool.c
1 /*
2  * Copyright (C) 2003-2015 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuTLS.
5  *
6  * GnuTLS is free software: you can redistribute it and/or modify it
7  * 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  * GnuTLS is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * 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
18  * <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22
23 #include <gnutls/gnutls.h>
24 #include <gnutls/x509.h>
25 #include <gnutls/openpgp.h>
26 #include <gnutls/pkcs12.h>
27 #include <gnutls/pkcs11.h>
28 #include <gnutls/abstract.h>
29 #include <gnutls/crypto.h>
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include <time.h>
36 #include <unistd.h>
37 #include <errno.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41
42 /* Gnulib portability files. */
43 #include <read-file.h>
44
45 #include <certtool-cfg.h>
46 #include <common.h>
47 #include "certtool-args.h"
48 #include "certtool-common.h"
49
50 static FILE *stdlog = NULL;
51
52 static void privkey_info_int(common_info_st *, gnutls_x509_privkey_t key);
53 static void print_crl_info(gnutls_x509_crl_t crl, FILE * out);
54 void pkcs7_info(void);
55 void pkcs8_info(void);
56 void pkcs8_info_int(gnutls_datum_t *data, unsigned format, 
57                         unsigned ignore_err, FILE *out, const char *tab);
58 void crq_info(void);
59 void smime_to_pkcs7(void);
60 void pkcs12_info(common_info_st *);
61 void generate_pkcs12(common_info_st *);
62 void generate_pkcs8(common_info_st *);
63 static void verify_chain(void);
64 void verify_crl(common_info_st * cinfo);
65 void pubkey_info(gnutls_x509_crt_t crt, common_info_st *);
66 void pgp_privkey_info(void);
67 void pgp_ring_info(void);
68 void certificate_info(int, common_info_st *);
69 void pgp_certificate_info(void);
70 void crl_info(void);
71 void privkey_info(common_info_st *);
72 static void cmd_parser(int argc, char **argv);
73 void generate_self_signed(common_info_st *);
74 void generate_request(common_info_st *);
75 static void print_certificate_info(gnutls_x509_crt_t crt, FILE * out,
76                                    unsigned int all);
77 static void verify_certificate(common_info_st * cinfo);
78
79 static void pubkey_keyid(common_info_st * cinfo);
80 static void certificate_fpr(common_info_st * cinfo);
81
82 FILE *outfile;
83 FILE *infile;
84 static gnutls_digest_algorithm_t default_dig;
85 static unsigned int incert_format, outcert_format;
86 static unsigned int req_key_type;
87 gnutls_certificate_print_formats_t full_format = GNUTLS_CRT_PRINT_FULL;
88
89 /* non interactive operation if set
90  */
91 int batch;
92 int ask_pass;
93
94
95 static void tls_log_func(int level, const char *str)
96 {
97         fprintf(stderr, "|<%d>| %s", level, str);
98 }
99
100 int main(int argc, char **argv)
101 {
102         cfg_init();
103         cmd_parser(argc, argv);
104
105         return 0;
106 }
107
108 static gnutls_x509_privkey_t
109 generate_private_key_int(common_info_st * cinfo)
110 {
111         gnutls_x509_privkey_t key;
112         int ret, key_type, bits;
113
114         key_type = req_key_type;
115
116         ret = gnutls_x509_privkey_init(&key);
117         if (ret < 0) {
118                 fprintf(stderr, "privkey_init: %s", gnutls_strerror(ret));
119                 exit(1);
120         }
121
122         bits = get_bits(key_type, cinfo->bits, cinfo->sec_param, 1);
123
124         fprintf(stdlog, "Generating a %d bit %s private key...\n",
125                 bits, gnutls_pk_algorithm_get_name(key_type));
126
127         if (bits < 256 && key_type == GNUTLS_PK_EC)
128                 fprintf(stderr,
129                         "Note that ECDSA keys with size less than 256 are not widely supported.\n\n");
130
131         if (bits > 1024 && key_type == GNUTLS_PK_DSA)
132                 fprintf(stderr,
133                         "Note that DSA keys with size over 1024 may cause incompatibility problems when used with earlier than TLS 1.2 versions.\n\n");
134
135         ret = gnutls_x509_privkey_generate(key, key_type, bits, 0);
136         if (ret < 0) {
137                 fprintf(stderr, "privkey_generate: %s\n",
138                         gnutls_strerror(ret));
139                 exit(1);
140         }
141
142         ret = gnutls_x509_privkey_verify_params(key);
143         if (ret < 0) {
144                 fprintf(stderr, "privkey_verify_params: %s\n",
145                         gnutls_strerror(ret));
146                 exit(1);
147         }
148
149         return key;
150 }
151
152 static int cipher_to_flags(const char *cipher)
153 {
154         if (cipher == NULL) {
155 #ifdef ENABLE_FIPS140
156                 return GNUTLS_PKCS_USE_PBES2_AES_128;
157 #else /* compatibility mode - most implementations don't support PBES2 with AES */
158                 return GNUTLS_PKCS_USE_PKCS12_3DES;
159 #endif
160         } else if (strcasecmp(cipher, "3des") == 0) {
161                 return GNUTLS_PKCS_USE_PBES2_3DES;
162         } else if (strcasecmp(cipher, "3des-pkcs12") == 0) {
163                 return GNUTLS_PKCS_USE_PKCS12_3DES;
164         } else if (strcasecmp(cipher, "arcfour") == 0) {
165                 return GNUTLS_PKCS_USE_PKCS12_ARCFOUR;
166         } else if (strcasecmp(cipher, "aes-128") == 0) {
167                 return GNUTLS_PKCS_USE_PBES2_AES_128;
168         } else if (strcasecmp(cipher, "aes-192") == 0) {
169                 return GNUTLS_PKCS_USE_PBES2_AES_192;
170         } else if (strcasecmp(cipher, "aes-256") == 0) {
171                 return GNUTLS_PKCS_USE_PBES2_AES_256;
172         } else if (strcasecmp(cipher, "rc2-40") == 0) {
173                 return GNUTLS_PKCS_USE_PKCS12_RC2_40;
174         }
175
176         fprintf(stderr, "unknown cipher %s\n", cipher);
177         exit(1);
178 }
179
180
181 static void
182 print_private_key(common_info_st * cinfo, gnutls_x509_privkey_t key)
183 {
184         int ret;
185         size_t size;
186
187         if (!key)
188                 return;
189
190
191         if (!cinfo->pkcs8) {
192                 /* Only print private key parameters when an unencrypted
193                  * format is used */
194                 if (outcert_format == GNUTLS_X509_FMT_PEM)
195                         privkey_info_int(cinfo, key);
196
197                 size = lbuffer_size;
198                 ret = gnutls_x509_privkey_export(key, outcert_format,
199                                                  lbuffer, &size);
200                 if (ret < 0) {
201                         fprintf(stderr, "privkey_export: %s",
202                                 gnutls_strerror(ret));
203                         exit(1);
204                 }
205         } else {
206                 unsigned int flags = 0;
207                 const char *pass;
208
209                 pass = get_password(cinfo, &flags, 0);
210                 flags |= cipher_to_flags(cinfo->pkcs_cipher);
211
212                 size = lbuffer_size;
213                 ret =
214                     gnutls_x509_privkey_export_pkcs8(key, outcert_format,
215                                                      pass, flags, lbuffer,
216                                                      &size);
217                 if (ret < 0) {
218                         fprintf(stderr, "privkey_export_pkcs8: %s\n",
219                                 gnutls_strerror(ret));
220                         exit(1);
221                 }
222         }
223
224         fwrite(lbuffer, 1, size, outfile);
225 }
226
227 static void generate_private_key(common_info_st * cinfo)
228 {
229         gnutls_x509_privkey_t key;
230
231         key = generate_private_key_int(cinfo);
232
233         print_private_key(cinfo, key);
234
235         gnutls_x509_privkey_deinit(key);
236 }
237
238
239 static gnutls_x509_crt_t
240 generate_certificate(gnutls_privkey_t * ret_key,
241                      gnutls_x509_crt_t ca_crt, int proxy,
242                      common_info_st * cinfo)
243 {
244         gnutls_x509_crt_t crt;
245         gnutls_privkey_t key = NULL;
246         gnutls_pubkey_t pubkey;
247         size_t size;
248         int ret;
249         int client;
250         int result, ca_status = 0, is_ike = 0, path_len;
251         time_t secs;
252         int vers;
253         unsigned int usage = 0, server, ask;
254         gnutls_x509_crq_t crq;  /* request */
255
256         ret = gnutls_x509_crt_init(&crt);
257         if (ret < 0) {
258                 fprintf(stderr, "crt_init: %s\n", gnutls_strerror(ret));
259                 exit(1);
260         }
261
262         crq = load_request(cinfo);
263
264         if (crq == NULL) {
265
266                 key = load_private_key(0, cinfo);
267
268                 pubkey = load_public_key_or_import(1, key, cinfo);
269
270                 if (!batch)
271                         fprintf(stderr,
272                                 "Please enter the details of the certificate's distinguished name. "
273                                 "Just press enter to ignore a field.\n");
274
275                 /* set the DN.
276                  */
277                 if (proxy) {
278                         result =
279                             gnutls_x509_crt_set_proxy_dn(crt, ca_crt, 0,
280                                                          NULL, 0);
281                         if (result < 0) {
282                                 fprintf(stderr, "set_proxy_dn: %s\n",
283                                         gnutls_strerror(result));
284                                 exit(1);
285                         }
286
287                         get_dn_crt_set(crt);
288                         get_cn_crt_set(crt);
289                 } else {
290                         get_dn_crt_set(crt);
291
292                         get_cn_crt_set(crt);
293                         get_uid_crt_set(crt);
294                         get_unit_crt_set(crt);
295                         get_organization_crt_set(crt);
296                         get_locality_crt_set(crt);
297                         get_state_crt_set(crt);
298                         get_country_crt_set(crt);
299                         get_dc_set(TYPE_CRT, crt);
300
301                         get_oid_crt_set(crt);
302                         get_key_purpose_set(TYPE_CRT, crt);
303
304                         if (!batch)
305                                 fprintf(stderr,
306                                         "This field should not be used in new certificates.\n");
307
308                         get_pkcs9_email_crt_set(crt);
309                 }
310
311                 result = gnutls_x509_crt_set_pubkey(crt, pubkey);
312                 if (result < 0) {
313                         fprintf(stderr, "set_key: %s\n",
314                                 gnutls_strerror(result));
315                         exit(1);
316                 }
317         } else {
318                 result = gnutls_x509_crt_set_crq(crt, crq);
319                 if (result < 0) {
320                         fprintf(stderr, "set_crq: %s\n",
321                                 gnutls_strerror(result));
322                         exit(1);
323                 }
324         }
325
326
327         {
328                 size_t serial_size;
329                 unsigned char serial[16];
330
331                 serial_size = sizeof(serial);
332
333                 get_serial(serial, &serial_size);
334
335                 result = gnutls_x509_crt_set_serial(crt, serial, serial_size);
336                 if (result < 0) {
337                         fprintf(stderr, "serial: %s\n",
338                                 gnutls_strerror(result));
339                         exit(1);
340                 }
341         }
342
343         if (!batch)
344                 fprintf(stderr, "\n\nActivation/Expiration time.\n");
345
346         secs = get_activation_date();
347
348         result = gnutls_x509_crt_set_activation_time(crt, secs);
349         if (result < 0) {
350                 fprintf(stderr, "set_activation: %s\n",
351                         gnutls_strerror(result));
352                 exit(1);
353         }
354
355         do {
356                 ask = 0;
357                 secs = get_expiration_date();
358
359                 if (ca_crt && (secs > gnutls_x509_crt_get_expiration_time(ca_crt))) {
360                         time_t exp = gnutls_x509_crt_get_expiration_time(ca_crt);
361                         fprintf(stderr, "\nExpiration time: %s", ctime(&secs));
362                         fprintf(stderr, "CA expiration time: %s", ctime(&exp));
363                         fprintf(stderr, "Warning: The time set exceeds the CA's expiration time\n");
364                         ask = 1;
365                 }
366         } while(batch == 0 && ask != 0 && read_yesno("Is it ok to proceed? (y/N): ", 0) == 0);
367
368
369         result = gnutls_x509_crt_set_expiration_time(crt, secs);
370         if (result < 0) {
371                 fprintf(stderr, "set_expiration: %s\n",
372                         gnutls_strerror(result));
373                 exit(1);
374         }
375
376         if (!batch)
377                 fprintf(stderr, "\n\nExtensions.\n");
378
379         /* do not allow extensions on a v1 certificate */
380         if (crq && get_crq_extensions_status() != 0) {
381                 result = gnutls_x509_crt_set_crq_extensions(crt, crq);
382                 if (result < 0) {
383                         fprintf(stderr, "set_crq: %s\n",
384                                 gnutls_strerror(result));
385                         exit(1);
386                 }
387         }
388
389         /* append additional extensions */
390         if (cinfo->v1_cert == 0) {
391
392                 if (proxy) {
393                         const char *policylanguage;
394                         char *policy;
395                         size_t policylen;
396                         int proxypathlen = get_path_len();
397
398                         if (!batch) {
399                                 printf
400                                     ("1.3.6.1.5.5.7.21.1 ::= id-ppl-inheritALL\n");
401                                 printf
402                                     ("1.3.6.1.5.5.7.21.2 ::= id-ppl-independent\n");
403                         }
404
405                         policylanguage =
406                             get_proxy_policy(&policy, &policylen);
407
408                         result =
409                             gnutls_x509_crt_set_proxy(crt, proxypathlen,
410                                                       policylanguage,
411                                                       policy, policylen);
412                         if (result < 0) {
413                                 fprintf(stderr, "set_proxy: %s\n",
414                                         gnutls_strerror(result));
415                                 exit(1);
416                         }
417                 }
418
419                 if (!proxy)
420                         ca_status = get_ca_status();
421                 if (ca_status)
422                         path_len = get_path_len();
423                 else
424                         path_len = -1;
425
426                 result =
427                     gnutls_x509_crt_set_basic_constraints(crt, ca_status,
428                                                           path_len);
429                 if (result < 0) {
430                         fprintf(stderr, "basic_constraints: %s\n",
431                                 gnutls_strerror(result));
432                         exit(1);
433                 }
434
435                 client = get_tls_client_status();
436                 if (client != 0) {
437                         result = gnutls_x509_crt_set_key_purpose_oid(crt,
438                                                                      GNUTLS_KP_TLS_WWW_CLIENT,
439                                                                      0);
440                         if (result < 0) {
441                                 fprintf(stderr, "key_kp: %s\n",
442                                         gnutls_strerror(result));
443                                 exit(1);
444                         }
445                 }
446
447                 is_ike = get_ipsec_ike_status();
448                 server = get_tls_server_status();
449
450                 get_dns_name_set(TYPE_CRT, crt);
451                 get_uri_set(TYPE_CRT, crt);
452                 get_ip_addr_set(TYPE_CRT, crt);
453                 get_policy_set(crt);
454
455                 if (server != 0) {
456                         result = 0;
457
458                         result =
459                             gnutls_x509_crt_set_key_purpose_oid(crt,
460                                                                 GNUTLS_KP_TLS_WWW_SERVER,
461                                                                 0);
462                         if (result < 0) {
463                                 fprintf(stderr, "key_kp: %s\n",
464                                         gnutls_strerror(result));
465                                 exit(1);
466                         }
467                 } else if (!proxy) {
468                         get_email_set(TYPE_CRT, crt);
469                 }
470
471                 if (!ca_status || server) {
472                         int pk;
473
474
475                         pk = gnutls_x509_crt_get_pk_algorithm(crt, NULL);
476
477                         if (pk == GNUTLS_PK_RSA) {      /* DSA and ECDSA keys can only sign. */
478                                 result = get_sign_status(server);
479                                 if (result)
480                                         usage |=
481                                             GNUTLS_KEY_DIGITAL_SIGNATURE;
482
483                                 result = get_encrypt_status(server);
484                                 if (result)
485                                         usage |=
486                                             GNUTLS_KEY_KEY_ENCIPHERMENT;
487                         } else
488                                 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
489
490                         if (is_ike) {
491                                 result =
492                                     gnutls_x509_crt_set_key_purpose_oid
493                                     (crt, GNUTLS_KP_IPSEC_IKE, 0);
494                                 if (result < 0) {
495                                         fprintf(stderr, "key_kp: %s\n",
496                                                 gnutls_strerror(result));
497                                         exit(1);
498                                 }
499                         }
500                 }
501
502                 result = get_key_agreement_status();
503                 if (result)
504                         usage |= GNUTLS_KEY_KEY_AGREEMENT;
505
506                 result = get_data_encipherment_status();
507                 if (result)
508                         usage |= GNUTLS_KEY_DATA_ENCIPHERMENT;
509
510                 result = get_non_repudiation_status();
511                 if (result)
512                         usage |= GNUTLS_KEY_NON_REPUDIATION;
513
514                 if (ca_status) {
515                         result = get_cert_sign_status();
516                         if (result)
517                                 usage |= GNUTLS_KEY_KEY_CERT_SIGN;
518
519                         result = get_crl_sign_status();
520                         if (result)
521                                 usage |= GNUTLS_KEY_CRL_SIGN;
522
523                         result = get_code_sign_status();
524                         if (result) {
525                                 result =
526                                     gnutls_x509_crt_set_key_purpose_oid
527                                     (crt, GNUTLS_KP_CODE_SIGNING, 0);
528                                 if (result < 0) {
529                                         fprintf(stderr, "key_kp: %s\n",
530                                                 gnutls_strerror(result));
531                                         exit(1);
532                                 }
533                         }
534
535                         crt_constraints_set(crt);
536
537                         result = get_ocsp_sign_status();
538                         if (result) {
539                                 result =
540                                     gnutls_x509_crt_set_key_purpose_oid
541                                     (crt, GNUTLS_KP_OCSP_SIGNING, 0);
542                                 if (result < 0) {
543                                         fprintf(stderr, "key_kp: %s\n",
544                                                 gnutls_strerror(result));
545                                         exit(1);
546                                 }
547                         }
548
549                         result = get_time_stamp_status();
550                         if (result) {
551                                 result =
552                                     gnutls_x509_crt_set_key_purpose_oid
553                                     (crt, GNUTLS_KP_TIME_STAMPING, 0);
554                                 if (result < 0) {
555                                         fprintf(stderr, "key_kp: %s\n",
556                                                 gnutls_strerror(result));
557                                         exit(1);
558                                 }
559                         }
560                 }
561                 get_ocsp_issuer_set(crt);
562                 get_ca_issuers_set(crt);
563
564                 if (usage != 0) {
565                         /* http://tools.ietf.org/html/rfc4945#section-5.1.3.2: if any KU is
566                            set, then either digitalSignature or the nonRepudiation bits in the
567                            KeyUsage extension MUST for all IKE certs */
568                         if (is_ike && (get_sign_status(server) != 1))
569                                 usage |= GNUTLS_KEY_NON_REPUDIATION;
570                         result = gnutls_x509_crt_set_key_usage(crt, usage);
571                         if (result < 0) {
572                                 fprintf(stderr, "key_usage: %s\n",
573                                         gnutls_strerror(result));
574                                 exit(1);
575                         }
576                 }
577
578                 /* Subject Key ID.
579                  */
580                 size = lbuffer_size;
581                 result = gnutls_x509_crt_get_key_id(crt, 0, lbuffer, &size);
582                 if (result >= 0) {
583                         result =
584                             gnutls_x509_crt_set_subject_key_id(crt, lbuffer,
585                                                                size);
586                         if (result < 0) {
587                                 fprintf(stderr, "set_subject_key_id: %s\n",
588                                         gnutls_strerror(result));
589                                 exit(1);
590                         }
591                 }
592
593                 /* Authority Key ID.
594                  */
595                 if (ca_crt != NULL) {
596                         size = lbuffer_size;
597                         result =
598                             gnutls_x509_crt_get_subject_key_id(ca_crt,
599                                                                lbuffer,
600                                                                &size,
601                                                                NULL);
602                         if (result >= 0) {
603                                 result =
604                                     gnutls_x509_crt_set_authority_key_id
605                                     (crt, lbuffer, size);
606                                 if (result < 0) {
607                                         fprintf(stderr,
608                                                 "set_authority_key_id: %s\n",
609                                                 gnutls_strerror(result));
610                                         exit(1);
611                                 }
612                         }
613                 }
614         }
615
616         /* Version.
617          */
618         if (cinfo->v1_cert != 0)
619                 vers = 1;
620         else
621                 vers = 3;
622         result = gnutls_x509_crt_set_version(crt, vers);
623         if (result < 0) {
624                 fprintf(stderr, "set_version: %s\n",
625                         gnutls_strerror(result));
626                 exit(1);
627         }
628
629         *ret_key = key;
630         return crt;
631
632 }
633
634 static gnutls_x509_crl_t
635 generate_crl(gnutls_x509_crt_t ca_crt, common_info_st * cinfo)
636 {
637         gnutls_x509_crl_t crl;
638         gnutls_x509_crt_t *crts;
639         size_t size;
640         int result;
641         unsigned int i;
642         time_t secs, now = time(0);
643
644         result = gnutls_x509_crl_init(&crl);
645         if (result < 0) {
646                 fprintf(stderr, "crl_init: %s\n", gnutls_strerror(result));
647                 exit(1);
648         }
649
650         crts = load_cert_list(0, &size, cinfo);
651
652         for (i = 0; i < size; i++) {
653                 result = gnutls_x509_crl_set_crt(crl, crts[i], now);
654                 if (result < 0) {
655                         fprintf(stderr, "crl_set_crt: %s\n",
656                                 gnutls_strerror(result));
657                         exit(1);
658                 }
659         }
660
661         result = gnutls_x509_crl_set_this_update(crl, now);
662         if (result < 0) {
663                 fprintf(stderr, "this_update: %s\n",
664                         gnutls_strerror(result));
665                 exit(1);
666         }
667
668         fprintf(stderr, "Update times.\n");
669         secs = get_crl_next_update();
670
671         result =
672             gnutls_x509_crl_set_next_update(crl, secs);
673         if (result < 0) {
674                 fprintf(stderr, "next_update: %s\n",
675                         gnutls_strerror(result));
676                 exit(1);
677         }
678
679         result = gnutls_x509_crl_set_version(crl, 2);
680         if (result < 0) {
681                 fprintf(stderr, "set_version: %s\n",
682                         gnutls_strerror(result));
683                 exit(1);
684         }
685
686         /* Authority Key ID.
687          */
688         if (ca_crt != NULL) {
689                 size = lbuffer_size;
690                 result = gnutls_x509_crt_get_subject_key_id(ca_crt, lbuffer,
691                                                             &size, NULL);
692                 if (result >= 0) {
693                         result =
694                             gnutls_x509_crl_set_authority_key_id(crl,
695                                                                  lbuffer,
696                                                                  size);
697                         if (result < 0) {
698                                 fprintf(stderr, "set_authority_key_id: %s\n",
699                                         gnutls_strerror(result));
700                                 exit(1);
701                         }
702
703                 }
704         }
705
706         {
707                 size_t serial_size;
708                 unsigned char serial[16];
709
710                 serial_size = sizeof(serial);
711
712                 get_crl_number(serial, &serial_size);
713
714                 result = gnutls_x509_crl_set_number(crl, serial, serial_size);
715                 if (result < 0) {
716                         fprintf(stderr, "crl set_number: %s\n",
717                                 gnutls_strerror(result));
718                         exit(1);
719                 }
720         }
721
722         return crl;
723 }
724
725 static gnutls_digest_algorithm_t get_dig_for_pub(gnutls_pubkey_t pubkey)
726 {
727         gnutls_digest_algorithm_t dig;
728         int result;
729         unsigned int mand;
730
731         result =
732             gnutls_pubkey_get_preferred_hash_algorithm(pubkey, &dig,
733                                                        &mand);
734         if (result < 0) {
735                 {
736                         fprintf(stderr,
737                                 "crt_get_preferred_hash_algorithm: %s\n",
738                                 gnutls_strerror(result));
739                         exit(1);
740                 }
741         }
742
743         /* if algorithm allows alternatives */
744         if (mand == 0 && default_dig != GNUTLS_DIG_UNKNOWN)
745                 dig = default_dig;
746
747         return dig;
748 }
749
750 static gnutls_digest_algorithm_t get_dig(gnutls_x509_crt_t crt)
751 {
752         gnutls_digest_algorithm_t dig;
753         gnutls_pubkey_t pubkey;
754         int result;
755
756         gnutls_pubkey_init(&pubkey);
757
758         result = gnutls_pubkey_import_x509(pubkey, crt, 0);
759         if (result < 0) {
760                 {
761                         fprintf(stderr, "gnutls_pubkey_import_x509: %s\n",
762                                 gnutls_strerror(result));
763                         exit(1);
764                 }
765         }
766
767         dig = get_dig_for_pub(pubkey);
768
769         gnutls_pubkey_deinit(pubkey);
770
771         return dig;
772 }
773
774 void generate_self_signed(common_info_st * cinfo)
775 {
776         gnutls_x509_crt_t crt;
777         gnutls_privkey_t key;
778         size_t size;
779         int result;
780
781         fprintf(stdlog, "Generating a self signed certificate...\n");
782
783         crt = generate_certificate(&key, NULL, 0, cinfo);
784
785         if (!key)
786                 key = load_private_key(1, cinfo);
787
788         get_crl_dist_point_set(crt);
789
790         print_certificate_info(crt, stdlog, 0);
791
792         fprintf(stdlog, "\n\nSigning certificate...\n");
793
794         result =
795             gnutls_x509_crt_privkey_sign(crt, crt, key, get_dig(crt), 0);
796         if (result < 0) {
797                 fprintf(stderr, "crt_sign: %s\n", gnutls_strerror(result));
798                 exit(1);
799         }
800
801         size = lbuffer_size;
802         result =
803             gnutls_x509_crt_export(crt, outcert_format, lbuffer, &size);
804         if (result < 0) {
805                 fprintf(stderr, "crt_export: %s\n", gnutls_strerror(result));
806                 exit(1);
807         }
808
809         fwrite(lbuffer, 1, size, outfile);
810
811         gnutls_x509_crt_deinit(crt);
812         gnutls_privkey_deinit(key);
813 }
814
815 static void generate_signed_certificate(common_info_st * cinfo)
816 {
817         gnutls_x509_crt_t crt;
818         gnutls_privkey_t key;
819         size_t size;
820         int result;
821         gnutls_privkey_t ca_key;
822         gnutls_x509_crt_t ca_crt;
823
824         fprintf(stdlog, "Generating a signed certificate...\n");
825
826         ca_key = load_ca_private_key(cinfo);
827         ca_crt = load_ca_cert(1, cinfo);
828
829         crt = generate_certificate(&key, ca_crt, 0, cinfo);
830
831         /* Copy the CRL distribution points.
832          */
833         gnutls_x509_crt_cpy_crl_dist_points(crt, ca_crt);
834         /* it doesn't matter if we couldn't copy the CRL dist points.
835          */
836
837         print_certificate_info(crt, stdlog, 0);
838
839         fprintf(stdlog, "\n\nSigning certificate...\n");
840
841         result =
842             gnutls_x509_crt_privkey_sign(crt, ca_crt, ca_key,
843                                          get_dig(ca_crt), 0);
844         if (result < 0) {
845                 fprintf(stderr, "crt_sign: %s\n", gnutls_strerror(result));
846                 exit(1);
847         }
848
849         size = lbuffer_size;
850         result =
851             gnutls_x509_crt_export(crt, outcert_format, lbuffer, &size);
852         if (result < 0) {
853                 fprintf(stderr, "crt_export: %s\n", gnutls_strerror(result));
854                 exit(1);
855         }
856
857         fwrite(lbuffer, 1, size, outfile);
858
859         gnutls_x509_crt_deinit(crt);
860         gnutls_privkey_deinit(key);
861         gnutls_privkey_deinit(ca_key);
862 }
863
864 static void generate_proxy_certificate(common_info_st * cinfo)
865 {
866         gnutls_x509_crt_t crt, eecrt;
867         gnutls_privkey_t key, eekey;
868         size_t size;
869         int result;
870
871         fprintf(stdlog, "Generating a proxy certificate...\n");
872
873         eekey = load_ca_private_key(cinfo);
874         eecrt = load_cert(1, cinfo);
875
876         crt = generate_certificate(&key, eecrt, 1, cinfo);
877
878         print_certificate_info(crt, stdlog, 0);
879
880         fprintf(stdlog, "\n\nSigning certificate...\n");
881
882         result =
883             gnutls_x509_crt_privkey_sign(crt, eecrt, eekey, get_dig(eecrt),
884                                          0);
885         if (result < 0) {
886                 fprintf(stderr, "crt_sign: %s\n", gnutls_strerror(result));
887                 exit(1);
888         }
889
890         size = lbuffer_size;
891         result =
892             gnutls_x509_crt_export(crt, outcert_format, lbuffer, &size);
893         if (result < 0) {
894                 fprintf(stderr, "crt_export: %s\n", gnutls_strerror(result));
895                 exit(1);
896         }
897
898         fwrite(lbuffer, 1, size, outfile);
899
900         gnutls_x509_crt_deinit(eecrt);
901         gnutls_x509_crt_deinit(crt);
902         gnutls_privkey_deinit(key);
903         gnutls_privkey_deinit(eekey);
904 }
905
906 static void generate_signed_crl(common_info_st * cinfo)
907 {
908         gnutls_x509_crl_t crl;
909         int result;
910         gnutls_privkey_t ca_key;
911         gnutls_x509_crt_t ca_crt;
912
913         fprintf(stdlog, "Generating a signed CRL...\n");
914
915         ca_key = load_ca_private_key(cinfo);
916         ca_crt = load_ca_cert(1, cinfo);
917         crl = generate_crl(ca_crt, cinfo);
918
919         fprintf(stdlog, "\n");
920         result =
921             gnutls_x509_crl_privkey_sign(crl, ca_crt, ca_key,
922                                          get_dig(ca_crt), 0);
923         if (result < 0) {
924                 fprintf(stderr, "crl_privkey_sign: %s\n",
925                         gnutls_strerror(result));
926                 exit(1);
927         }
928
929         print_crl_info(crl, stdlog);
930
931         gnutls_privkey_deinit(ca_key);
932         gnutls_x509_crl_deinit(crl);
933 }
934
935 static void update_signed_certificate(common_info_st * cinfo)
936 {
937         gnutls_x509_crt_t crt;
938         size_t size;
939         int result;
940         gnutls_privkey_t ca_key;
941         gnutls_x509_crt_t ca_crt;
942         time_t tim;
943
944         fprintf(stdlog, "Generating a signed certificate...\n");
945
946         ca_key = load_ca_private_key(cinfo);
947         ca_crt = load_ca_cert(1, cinfo);
948         crt = load_cert(1, cinfo);
949
950         fprintf(stderr, "Activation/Expiration time.\n");
951         tim = get_activation_date();
952
953         result = gnutls_x509_crt_set_activation_time(crt, tim);
954         if (result < 0) {
955                 fprintf(stderr, "set_activation: %s\n",
956                         gnutls_strerror(result));
957                 exit(1);
958         }
959
960         tim = get_expiration_date();
961
962         result = gnutls_x509_crt_set_expiration_time(crt, tim);
963         if (result < 0) {
964                 fprintf(stderr, "set_expiration: %s\n",
965                         gnutls_strerror(result));
966                 exit(1);
967         }
968
969         fprintf(stderr, "\n\nSigning certificate...\n");
970
971         result =
972             gnutls_x509_crt_privkey_sign(crt, ca_crt, ca_key,
973                                          get_dig(ca_crt), 0);
974         if (result < 0) {
975                 fprintf(stderr, "crt_sign: %s\n", gnutls_strerror(result));
976                 exit(1);
977         }
978
979         size = lbuffer_size;
980         result =
981             gnutls_x509_crt_export(crt, outcert_format, lbuffer, &size);
982         if (result < 0) {
983                 fprintf(stderr, "crt_export: %s\n", gnutls_strerror(result));
984                 exit(1);
985         }
986
987         fwrite(lbuffer, 1, size, outfile);
988
989         gnutls_x509_crt_deinit(crt);
990 }
991
992 static void cmd_parser(int argc, char **argv)
993 {
994         int ret, privkey_op = 0;
995         common_info_st cinfo;
996
997         optionProcess(&certtoolOptions, argc, argv);
998
999         if (HAVE_OPT(STDOUT_INFO)) {
1000                 /* print informational messages on stdout instead of stderr */
1001                 stdlog = stdout;
1002         } else {
1003                 stdlog = stderr;
1004         }
1005
1006         if (HAVE_OPT(GENERATE_PRIVKEY) || HAVE_OPT(GENERATE_REQUEST) ||
1007             HAVE_OPT(KEY_INFO) || HAVE_OPT(PGP_KEY_INFO))
1008                 privkey_op = 1;
1009
1010         if (HAVE_OPT(HEX_NUMBERS))
1011                 full_format = GNUTLS_CRT_PRINT_FULL_NUMBERS;
1012
1013         if (HAVE_OPT(OUTFILE)) {
1014                 outfile = safe_open_rw(OPT_ARG(OUTFILE), privkey_op);
1015                 if (outfile == NULL) {
1016                         fprintf(stderr, "%s", OPT_ARG(OUTFILE));
1017                         exit(1);
1018                 }
1019         } else
1020                 outfile = stdout;
1021
1022
1023         if (HAVE_OPT(INFILE)) {
1024                 struct stat st;
1025                 if (stat(OPT_ARG(INFILE), &st) == 0) {
1026                         fix_lbuffer(2*st.st_size);
1027                 }
1028
1029                 infile = fopen(OPT_ARG(INFILE), "rb");
1030                 if (infile == NULL) {
1031                         fprintf(stderr, "%s", OPT_ARG(INFILE));
1032                         exit(1);
1033                 }
1034         } else
1035                 infile = stdin;
1036
1037         fix_lbuffer(0);
1038
1039         if (HAVE_OPT(INDER) || HAVE_OPT(INRAW))
1040                 incert_format = GNUTLS_X509_FMT_DER;
1041         else
1042                 incert_format = GNUTLS_X509_FMT_PEM;
1043
1044         if (HAVE_OPT(OUTDER) || HAVE_OPT(OUTRAW))
1045                 outcert_format = GNUTLS_X509_FMT_DER;
1046         else
1047                 outcert_format = GNUTLS_X509_FMT_PEM;
1048
1049         if (HAVE_OPT(DSA))
1050                 req_key_type = GNUTLS_PK_DSA;
1051         else if (HAVE_OPT(ECC))
1052                 req_key_type = GNUTLS_PK_ECC;
1053         else
1054                 req_key_type = GNUTLS_PK_RSA;
1055
1056         default_dig = GNUTLS_DIG_UNKNOWN;
1057         if (HAVE_OPT(HASH)) {
1058                 if (strcasecmp(OPT_ARG(HASH), "md5") == 0) {
1059                         fprintf(stderr,
1060                                 "Warning: MD5 is broken, and should not be used any more for digital signatures.\n");
1061                         default_dig = GNUTLS_DIG_MD5;
1062                 } else if (strcasecmp(OPT_ARG(HASH), "sha1") == 0)
1063                         default_dig = GNUTLS_DIG_SHA1;
1064                 else if (strcasecmp(OPT_ARG(HASH), "sha256") == 0)
1065                         default_dig = GNUTLS_DIG_SHA256;
1066                 else if (strcasecmp(OPT_ARG(HASH), "sha224") == 0)
1067                         default_dig = GNUTLS_DIG_SHA224;
1068                 else if (strcasecmp(OPT_ARG(HASH), "sha384") == 0)
1069                         default_dig = GNUTLS_DIG_SHA384;
1070                 else if (strcasecmp(OPT_ARG(HASH), "sha512") == 0)
1071                         default_dig = GNUTLS_DIG_SHA512;
1072                 else if (strcasecmp(OPT_ARG(HASH), "rmd160") == 0)
1073                         default_dig = GNUTLS_DIG_RMD160;
1074                 else {
1075                         fprintf(stderr, "invalid hash: %s\n", OPT_ARG(HASH));
1076                         exit(1);
1077                 }
1078         }
1079
1080         batch = 0;
1081         if (HAVE_OPT(TEMPLATE)) {
1082                 batch = 1;
1083                 template_parse(OPT_ARG(TEMPLATE));
1084         }
1085
1086         ask_pass = ENABLED_OPT(ASK_PASS);
1087
1088         gnutls_global_set_log_function(tls_log_func);
1089
1090         if (HAVE_OPT(DEBUG)) {
1091                 gnutls_global_set_log_level(OPT_VALUE_DEBUG);
1092                 printf("Setting log level to %d\n", (int) OPT_VALUE_DEBUG);
1093         }
1094
1095         if ((ret = gnutls_global_init()) < 0) {
1096                 fprintf(stderr, "global_init: %s\n", gnutls_strerror(ret));
1097                 exit(1);
1098         }
1099
1100         memset(&cinfo, 0, sizeof(cinfo));
1101 #ifdef ENABLE_PKCS11
1102         if (HAVE_OPT(PROVIDER)) {
1103                 ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
1104                 if (ret < 0)
1105                         fprintf(stderr, "pkcs11_init: %s",
1106                                 gnutls_strerror(ret));
1107                 else {
1108                         ret =
1109                             gnutls_pkcs11_add_provider(OPT_ARG(PROVIDER),
1110                                                        NULL);
1111                         if (ret < 0) {
1112                                 fprintf(stderr, "pkcs11_add_provider: %s",
1113                                         gnutls_strerror(ret));
1114                                 exit(1);
1115                         }
1116                 }
1117         }
1118
1119         pkcs11_common(&cinfo);
1120 #endif
1121
1122         if (HAVE_OPT(VERBOSE))
1123                 cinfo.verbose = 1;
1124
1125         cinfo.batch = batch;
1126         cinfo.cprint = HAVE_OPT(CPRINT);
1127
1128         if (HAVE_OPT(LOAD_PRIVKEY))
1129                 cinfo.privkey = OPT_ARG(LOAD_PRIVKEY);
1130
1131         cinfo.v1_cert = HAVE_OPT(V1);
1132         if (HAVE_OPT(NO_CRQ_EXTENSIONS))
1133                 cinfo.crq_extensions = 0;
1134         else
1135                 cinfo.crq_extensions = 1;
1136
1137         if (HAVE_OPT(LOAD_PUBKEY))
1138                 cinfo.pubkey = OPT_ARG(LOAD_PUBKEY);
1139
1140         cinfo.pkcs8 = HAVE_OPT(PKCS8);
1141         cinfo.incert_format = incert_format;
1142         cinfo.outcert_format = outcert_format;
1143
1144         if (HAVE_OPT(LOAD_CERTIFICATE))
1145                 cinfo.cert = OPT_ARG(LOAD_CERTIFICATE);
1146
1147         if (HAVE_OPT(LOAD_REQUEST))
1148                 cinfo.request = OPT_ARG(LOAD_REQUEST);
1149
1150         if (HAVE_OPT(LOAD_CA_CERTIFICATE))
1151                 cinfo.ca = OPT_ARG(LOAD_CA_CERTIFICATE);
1152
1153         if (HAVE_OPT(LOAD_CA_PRIVKEY))
1154                 cinfo.ca_privkey = OPT_ARG(LOAD_CA_PRIVKEY);
1155
1156         if (HAVE_OPT(BITS))
1157                 cinfo.bits = OPT_VALUE_BITS;
1158
1159         if (HAVE_OPT(CURVE)) {
1160                 gnutls_ecc_curve_t curve = str_to_curve(OPT_ARG(CURVE));
1161                 cinfo.bits = GNUTLS_CURVE_TO_BITS(curve);
1162         }
1163
1164         if (HAVE_OPT(SEC_PARAM))
1165                 cinfo.sec_param = OPT_ARG(SEC_PARAM);
1166
1167         if (HAVE_OPT(PKCS_CIPHER))
1168                 cinfo.pkcs_cipher = OPT_ARG(PKCS_CIPHER);
1169
1170         if (HAVE_OPT(PASSWORD)) {
1171                 cinfo.password = OPT_ARG(PASSWORD);
1172                 if (HAVE_OPT(GENERATE_PRIVKEY) && cinfo.pkcs8 == 0) {
1173                         fprintf(stderr, "Assuming PKCS #8 format...\n");
1174                         cinfo.pkcs8 = 1;
1175                 }
1176         }
1177
1178         if (HAVE_OPT(NULL_PASSWORD)) {
1179                 cinfo.null_password = 1;
1180                 cinfo.password = "";
1181         }
1182
1183         if (HAVE_OPT(EMPTY_PASSWORD)) {
1184                 cinfo.empty_password = 1;
1185                 cinfo.password = "";
1186         }
1187
1188         if (HAVE_OPT(GENERATE_SELF_SIGNED))
1189                 generate_self_signed(&cinfo);
1190         else if (HAVE_OPT(GENERATE_CERTIFICATE))
1191                 generate_signed_certificate(&cinfo);
1192         else if (HAVE_OPT(GENERATE_PROXY))
1193                 generate_proxy_certificate(&cinfo);
1194         else if (HAVE_OPT(GENERATE_CRL))
1195                 generate_signed_crl(&cinfo);
1196         else if (HAVE_OPT(UPDATE_CERTIFICATE))
1197                 update_signed_certificate(&cinfo);
1198         else if (HAVE_OPT(GENERATE_PRIVKEY))
1199                 generate_private_key(&cinfo);
1200         else if (HAVE_OPT(GENERATE_REQUEST))
1201                 generate_request(&cinfo);
1202         else if (HAVE_OPT(VERIFY_CHAIN))
1203                 verify_chain();
1204         else if (HAVE_OPT(VERIFY))
1205                 verify_certificate(&cinfo);
1206         else if (HAVE_OPT(VERIFY_CRL))
1207                 verify_crl(&cinfo);
1208         else if (HAVE_OPT(CERTIFICATE_INFO))
1209                 certificate_info(0, &cinfo);
1210         else if (HAVE_OPT(DH_INFO))
1211                 dh_info(infile, outfile, &cinfo);
1212         else if (HAVE_OPT(CERTIFICATE_PUBKEY))
1213                 certificate_info(1, &cinfo);
1214         else if (HAVE_OPT(KEY_INFO))
1215                 privkey_info(&cinfo);
1216         else if (HAVE_OPT(PUBKEY_INFO))
1217                 pubkey_info(NULL, &cinfo);
1218         else if (HAVE_OPT(FINGERPRINT))
1219                 certificate_fpr(&cinfo);
1220         else if (HAVE_OPT(KEY_ID))
1221                 pubkey_keyid(&cinfo);
1222         else if (HAVE_OPT(TO_P12))
1223                 generate_pkcs12(&cinfo);
1224         else if (HAVE_OPT(P12_INFO))
1225                 pkcs12_info(&cinfo);
1226         else if (HAVE_OPT(GENERATE_DH_PARAMS))
1227                 generate_prime(outfile, 1, &cinfo);
1228         else if (HAVE_OPT(GET_DH_PARAMS))
1229                 generate_prime(outfile, 0, &cinfo);
1230         else if (HAVE_OPT(CRL_INFO))
1231                 crl_info();
1232         else if (HAVE_OPT(P7_INFO))
1233                 pkcs7_info();
1234         else if (HAVE_OPT(P8_INFO))
1235                 pkcs8_info();
1236         else if (HAVE_OPT(SMIME_TO_P7))
1237                 smime_to_pkcs7();
1238         else if (HAVE_OPT(TO_P8))
1239                 generate_pkcs8(&cinfo);
1240 #ifdef ENABLE_OPENPGP
1241         else if (HAVE_OPT(PGP_CERTIFICATE_INFO))
1242                 pgp_certificate_info();
1243         else if (HAVE_OPT(PGP_KEY_INFO))
1244                 pgp_privkey_info();
1245         else if (HAVE_OPT(PGP_RING_INFO))
1246                 pgp_ring_info();
1247 #endif
1248         else if (HAVE_OPT(CRQ_INFO))
1249                 crq_info();
1250         else
1251                 USAGE(1);
1252
1253         fclose(outfile);
1254
1255 #ifdef ENABLE_PKCS11
1256         gnutls_pkcs11_deinit();
1257 #endif
1258         gnutls_global_deinit();
1259 }
1260
1261 #define MAX_CRTS 500
1262 void certificate_info(int pubkey, common_info_st * cinfo)
1263 {
1264         gnutls_x509_crt_t crt[MAX_CRTS];
1265         size_t size;
1266         int ret, i, count;
1267         gnutls_datum_t pem;
1268         unsigned int crt_num;
1269
1270         pem.data = (void *) fread_file(infile, &size);
1271         pem.size = size;
1272
1273         crt_num = MAX_CRTS;
1274         ret =
1275             gnutls_x509_crt_list_import(crt, &crt_num, &pem, incert_format,
1276                                         GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
1277         if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
1278                 fprintf(stderr, "too many certificates (%d); "
1279                         "will only read the first %d", crt_num, MAX_CRTS);
1280                 crt_num = MAX_CRTS;
1281                 ret = gnutls_x509_crt_list_import(crt, &crt_num, &pem,
1282                                                   incert_format, 0);
1283         }
1284         if (ret < 0) {
1285                 fprintf(stderr, "import error: %s\n", gnutls_strerror(ret));
1286                 exit(1);
1287         }
1288
1289         free(pem.data);
1290
1291         count = ret;
1292
1293         if (count > 1 && outcert_format == GNUTLS_X509_FMT_DER) {
1294                 fprintf(stderr,
1295                         "cannot output multiple certificates in DER format; "
1296                         "using PEM instead");
1297                 outcert_format = GNUTLS_X509_FMT_PEM;
1298         }
1299
1300         for (i = 0; i < count; i++) {
1301                 if (i > 0)
1302                         fprintf(outfile, "\n");
1303
1304                 if (outcert_format == GNUTLS_X509_FMT_PEM)
1305                         print_certificate_info(crt[i], outfile, 1);
1306
1307                 if (pubkey)
1308                         pubkey_info(crt[i], cinfo);
1309                 else {
1310                         size = lbuffer_size;
1311                         ret =
1312                             gnutls_x509_crt_export(crt[i], outcert_format,
1313                                                    lbuffer, &size);
1314                         if (ret < 0) {
1315                                 fprintf(stderr, "export error: %s\n",
1316                                         gnutls_strerror(ret));
1317                                 exit(1);
1318                         }
1319
1320                         fwrite(lbuffer, 1, size, outfile);
1321                 }
1322
1323                 gnutls_x509_crt_deinit(crt[i]);
1324         }
1325 }
1326
1327 #ifdef ENABLE_OPENPGP
1328
1329 void pgp_certificate_info(void)
1330 {
1331         gnutls_openpgp_crt_t crt;
1332         size_t size;
1333         int ret;
1334         gnutls_datum_t pem, out_data;
1335         unsigned int verify_status;
1336
1337         pem.data = (void *) fread_file(infile, &size);
1338         pem.size = size;
1339
1340         ret = gnutls_openpgp_crt_init(&crt);
1341         if (ret < 0) {
1342                 fprintf(stderr, "openpgp_crt_init: %s\n",
1343                         gnutls_strerror(ret));
1344                 exit(1);
1345         }
1346
1347         ret = gnutls_openpgp_crt_import(crt, &pem, incert_format);
1348
1349         if (ret < 0) {
1350                 fprintf(stderr, "import error: %s\n", gnutls_strerror(ret));
1351                 exit(1);
1352         }
1353
1354         free(pem.data);
1355
1356         if (outcert_format == GNUTLS_OPENPGP_FMT_BASE64) {
1357                 ret = gnutls_openpgp_crt_print(crt, 0, &out_data);
1358
1359                 if (ret == 0) {
1360                         fprintf(outfile, "%s\n", out_data.data);
1361                         gnutls_free(out_data.data);
1362                 }
1363         }
1364
1365
1366         ret = gnutls_openpgp_crt_verify_self(crt, 0, &verify_status);
1367         if (ret < 0) {
1368                 {
1369                         fprintf(stderr, "verify signature error: %s\n",
1370                                 gnutls_strerror(ret));
1371                         exit(1);
1372                 }
1373         }
1374
1375         if (verify_status & GNUTLS_CERT_INVALID) {
1376                 fprintf(outfile,
1377                         "Self Signature verification: failed\n\n");
1378         } else {
1379                 fprintf(outfile,
1380                         "Self Signature verification: ok (%x)\n\n",
1381                         verify_status);
1382         }
1383
1384         size = lbuffer_size;
1385         ret =
1386             gnutls_openpgp_crt_export(crt, outcert_format, lbuffer, &size);
1387         if (ret < 0) {
1388                 fprintf(stderr, "export error: %s\n", gnutls_strerror(ret));
1389                 exit(1);
1390         }
1391
1392         fprintf(outfile, "%s\n", lbuffer);
1393         gnutls_openpgp_crt_deinit(crt);
1394 }
1395
1396 void pgp_privkey_info(void)
1397 {
1398         gnutls_openpgp_privkey_t key;
1399         unsigned char keyid[GNUTLS_OPENPGP_KEYID_SIZE];
1400         size_t size;
1401         int ret, i, subkeys, bits = 0;
1402         gnutls_datum_t pem;
1403         const char *cprint;
1404
1405         size = fread(lbuffer, 1, lbuffer_size - 1, infile);
1406         lbuffer[size] = 0;
1407
1408         gnutls_openpgp_privkey_init(&key);
1409
1410         pem.data = lbuffer;
1411         pem.size = size;
1412
1413         ret = gnutls_openpgp_privkey_import(key, &pem, incert_format,
1414                                             NULL, 0);
1415
1416         if (ret < 0) {
1417                 fprintf(stderr, "import error: %s\n", gnutls_strerror(ret));
1418                 exit(1);
1419         }
1420
1421         /* Public key algorithm
1422          */
1423         subkeys = gnutls_openpgp_privkey_get_subkey_count(key);
1424         if (subkeys < 0) {
1425                 fprintf(stderr, "privkey_get_subkey_count: %s\n",
1426                         gnutls_strerror(subkeys));
1427                 exit(1);
1428         }
1429
1430         for (i = -1; i < subkeys; i++) {
1431
1432                 if (i != -1)
1433                         fprintf(outfile, "Subkey[%d]:\n", i);
1434
1435                 fprintf(outfile, "Public Key Info:\n");
1436
1437                 if (i == -1)
1438                         ret =
1439                             gnutls_openpgp_privkey_get_pk_algorithm(key,
1440                                                                     NULL);
1441                 else
1442                         ret =
1443                             gnutls_openpgp_privkey_get_subkey_pk_algorithm
1444                             (key, i, NULL);
1445
1446                 fprintf(outfile, "\tPublic Key Algorithm: ");
1447                 cprint = gnutls_pk_algorithm_get_name(ret);
1448                 fprintf(outfile, "%s\n", cprint ? cprint : "Unknown");
1449                 fprintf(outfile, "\tKey Security Level: %s\n",
1450                         gnutls_sec_param_get_name
1451                         (gnutls_openpgp_privkey_sec_param(key)));
1452
1453                 /* Print the raw public and private keys
1454                  */
1455
1456                 if (ret == GNUTLS_PK_RSA) {
1457                         gnutls_datum_t m, e, d, p, q, u;
1458
1459                         if (i == -1)
1460                                 ret =
1461                                     gnutls_openpgp_privkey_export_rsa_raw
1462                                     (key, &m, &e, &d, &p, &q, &u);
1463                         else
1464                                 ret =
1465                                     gnutls_openpgp_privkey_export_subkey_rsa_raw
1466                                     (key, i, &m, &e, &d, &p, &q, &u);
1467                         if (ret < 0)
1468                                 fprintf(stderr,
1469                                         "Error in key RSA data export: %s\n",
1470                                         gnutls_strerror(ret));
1471                         else
1472                                 print_rsa_pkey(outfile, &m, &e, &d, &p, &q,
1473                                                &u, NULL, NULL,
1474                                                HAVE_OPT(CPRINT));
1475
1476                         bits = m.size * 8;
1477                 } else if (ret == GNUTLS_PK_DSA) {
1478                         gnutls_datum_t p, q, g, y, x;
1479
1480                         if (i == -1)
1481                                 ret =
1482                                     gnutls_openpgp_privkey_export_dsa_raw
1483                                     (key, &p, &q, &g, &y, &x);
1484                         else
1485                                 ret =
1486                                     gnutls_openpgp_privkey_export_subkey_dsa_raw
1487                                     (key, i, &p, &q, &g, &y, &x);
1488                         if (ret < 0)
1489                                 fprintf(stderr,
1490                                         "Error in key DSA data export: %s\n",
1491                                         gnutls_strerror(ret));
1492                         else
1493                                 print_dsa_pkey(outfile, &x, &y, &p, &q, &g,
1494                                                HAVE_OPT(CPRINT));
1495
1496                         bits = y.size * 8;
1497                 }
1498
1499                 fprintf(outfile, "\n");
1500
1501                 size = lbuffer_size;
1502                 if (i == -1)
1503                         ret =
1504                             gnutls_openpgp_privkey_get_key_id(key, keyid);
1505                 else
1506                         ret =
1507                             gnutls_openpgp_privkey_get_subkey_id(key, i,
1508                                                                  keyid);
1509
1510                 if (ret < 0) {
1511                         fprintf(stderr,
1512                                 "Error in key id calculation: %s\n",
1513                                 gnutls_strerror(ret));
1514                 } else {
1515                         fprintf(outfile, "Public key ID: %s\n",
1516                                 raw_to_string(keyid, 8));
1517                 }
1518
1519                 size = lbuffer_size;
1520                 if (i == -1)
1521                         ret =
1522                             gnutls_openpgp_privkey_get_fingerprint(key,
1523                                                                    lbuffer,
1524                                                                    &size);
1525                 else
1526                         ret =
1527                             gnutls_openpgp_privkey_get_subkey_fingerprint
1528                             (key, i, lbuffer, &size);
1529
1530                 if (ret < 0) {
1531                         fprintf(stderr,
1532                                 "Error in fingerprint calculation: %s\n",
1533                                 gnutls_strerror(ret));
1534                 } else {
1535                         gnutls_datum_t art;
1536
1537                         fprintf(outfile, "Fingerprint: %s\n",
1538                                 raw_to_string(lbuffer, size));
1539
1540                         ret =
1541                             gnutls_random_art(GNUTLS_RANDOM_ART_OPENSSH,
1542                                               cprint, bits, lbuffer, size,
1543                                               &art);
1544                         if (ret >= 0) {
1545                                 fprintf(outfile,
1546                                         "Fingerprint's random art:\n%s\n\n",
1547                                         art.data);
1548                                 gnutls_free(art.data);
1549                         }
1550                 }
1551         }
1552
1553         size = lbuffer_size;
1554         ret = gnutls_openpgp_privkey_export(key, GNUTLS_OPENPGP_FMT_BASE64,
1555                                             NULL, 0, lbuffer, &size);
1556         if (ret < 0) {
1557                 fprintf(stderr, "export error: %s\n", gnutls_strerror(ret));
1558                 exit(1);
1559         }
1560
1561         fprintf(outfile, "\n%s\n", lbuffer);
1562
1563         gnutls_openpgp_privkey_deinit(key);
1564 }
1565
1566 void pgp_ring_info(void)
1567 {
1568         gnutls_openpgp_keyring_t ring;
1569         gnutls_openpgp_crt_t crt;
1570         size_t size;
1571         int ret, i, count;
1572         gnutls_datum_t pem;
1573
1574         pem.data = (void *) fread_file(infile, &size);
1575         pem.size = size;
1576
1577         ret = gnutls_openpgp_keyring_init(&ring);
1578         if (ret < 0) {
1579                 fprintf(stderr, "openpgp_keyring_init: %s\n",
1580                         gnutls_strerror(ret));
1581                 exit(1);
1582         }
1583
1584         ret = gnutls_openpgp_keyring_import(ring, &pem, incert_format);
1585
1586         if (ret < 0) {
1587                 fprintf(stderr, "import error: %s\n", gnutls_strerror(ret));
1588                 exit(1);
1589         }
1590
1591         free(pem.data);
1592
1593         count = gnutls_openpgp_keyring_get_crt_count(ring);
1594         if (count >= 0)
1595                 fprintf(outfile,
1596                         "Keyring contains %d OpenPGP certificates\n\n",
1597                         count);
1598         else {
1599                 fprintf(stderr, "keyring error: %s\n",
1600                         gnutls_strerror(count));
1601                 exit(1);
1602         }
1603
1604         for (i = 0; i < count; i++) {
1605                 ret = gnutls_openpgp_keyring_get_crt(ring, i, &crt);
1606                 if (ret < 0) {
1607                         fprintf(stderr, "export error: %s\n",
1608                                 gnutls_strerror(ret));
1609                         exit(1);
1610                 }
1611
1612                 size = lbuffer_size;
1613                 ret = gnutls_openpgp_crt_export(crt, outcert_format,
1614                                                 lbuffer, &size);
1615                 if (ret < 0) {
1616                         fprintf(stderr, "export error: %s\n",
1617                                 gnutls_strerror(ret));
1618                         exit(1);
1619                 }
1620
1621                 fwrite(lbuffer, 1, size, outfile);
1622                 fprintf(outfile, "\n\n");
1623
1624                 gnutls_openpgp_crt_deinit(crt);
1625
1626
1627         }
1628
1629         gnutls_openpgp_keyring_deinit(ring);
1630 }
1631
1632
1633 #endif
1634
1635
1636
1637 static void
1638 print_certificate_info(gnutls_x509_crt_t crt, FILE * out, unsigned int all)
1639 {
1640         gnutls_datum_t data;
1641         int ret;
1642
1643         if (all)
1644                 ret = gnutls_x509_crt_print(crt, full_format, &data);
1645         else
1646                 ret =
1647                     gnutls_x509_crt_print(crt,
1648                                           GNUTLS_CRT_PRINT_UNSIGNED_FULL,
1649                                           &data);
1650         if (ret == 0) {
1651                 fprintf(out, "%s\n", data.data);
1652                 gnutls_free(data.data);
1653         }
1654
1655         if (out == stderr && batch == 0)        /* interactive */
1656                 if (read_yesno("Is the above information ok? (y/N): ", 0)
1657                     == 0) {
1658                         exit(1);
1659                 }
1660 }
1661
1662 static void print_crl_info(gnutls_x509_crl_t crl, FILE * out)
1663 {
1664         gnutls_datum_t data;
1665         int ret;
1666         size_t size;
1667
1668         if (outcert_format == GNUTLS_X509_FMT_PEM) {
1669                 ret = gnutls_x509_crl_print(crl, full_format, &data);
1670                 if (ret < 0) {
1671                         fprintf(stderr, "crl_print: %s\n", gnutls_strerror(ret));
1672                         exit(1);
1673                 }
1674                 fprintf(out, "%s\n", data.data);
1675
1676                 gnutls_free(data.data);
1677         }
1678
1679         size = lbuffer_size;
1680         ret =
1681             gnutls_x509_crl_export(crl, outcert_format, lbuffer,
1682                                    &size);
1683         if (ret < 0) {
1684                 fprintf(stderr, "crl_export: %s\n", gnutls_strerror(ret));
1685                 exit(1);
1686         }
1687
1688         fwrite(lbuffer, 1, size, outfile);
1689 }
1690
1691 void crl_info(void)
1692 {
1693         gnutls_x509_crl_t crl;
1694         int ret;
1695         size_t size;
1696         gnutls_datum_t pem;
1697
1698         ret = gnutls_x509_crl_init(&crl);
1699         if (ret < 0) {
1700                 fprintf(stderr, "crl_init: %s\n", gnutls_strerror(ret));
1701                 exit(1);
1702         }
1703
1704         pem.data = (void *) fread_file(infile, &size);
1705         pem.size = size;
1706
1707         if (!pem.data) {
1708                 fprintf(stderr, "%s", infile ? "file" : "standard input");
1709                 exit(1);
1710         }
1711
1712         ret = gnutls_x509_crl_import(crl, &pem, incert_format);
1713
1714         free(pem.data);
1715         if (ret < 0) {
1716                 fprintf(stderr, "import error: %s\n", gnutls_strerror(ret));
1717                 exit(1);
1718         }
1719
1720         print_crl_info(crl, outfile);
1721
1722         gnutls_x509_crl_deinit(crl);
1723 }
1724
1725 static void print_crq_info(gnutls_x509_crq_t crq, FILE * out)
1726 {
1727         gnutls_datum_t data;
1728         int ret;
1729         size_t size;
1730
1731         if (outcert_format == GNUTLS_X509_FMT_PEM) {
1732                 ret = gnutls_x509_crq_print(crq, full_format, &data);
1733                 if (ret < 0) {
1734                         fprintf(stderr, "crq_print: %s\n",
1735                                 gnutls_strerror(ret));
1736                         exit(1);
1737                 }
1738
1739                 fprintf(out, "%s\n", data.data);
1740
1741                 gnutls_free(data.data);
1742         }
1743
1744         ret = gnutls_x509_crq_verify(crq, 0);
1745         if (ret < 0) {
1746                 fprintf(out, "Self signature: FAILED\n\n");
1747         } else {
1748                 fprintf(out, "Self signature: verified\n\n");
1749         }
1750
1751         size = lbuffer_size;
1752         ret = gnutls_x509_crq_export(crq, outcert_format, lbuffer, &size);
1753         if (ret < 0) {
1754                 fprintf(stderr, "crq_export: %s\n", gnutls_strerror(ret));
1755                 exit(1);
1756         }
1757
1758         fwrite(lbuffer, 1, size, outfile);
1759 }
1760
1761 void crq_info(void)
1762 {
1763         gnutls_x509_crq_t crq;
1764         int ret;
1765         size_t size;
1766         gnutls_datum_t pem;
1767
1768         ret = gnutls_x509_crq_init(&crq);
1769         if (ret < 0) {
1770                 fprintf(stderr, "crq_init: %s\n", gnutls_strerror(ret));
1771                 exit(1);
1772         }
1773
1774         pem.data = (void *) fread_file(infile, &size);
1775         pem.size = size;
1776
1777         if (!pem.data) {
1778                 fprintf(stderr, "%s", infile ? "file" : "standard input");
1779                 exit(1);
1780         }
1781
1782         ret = gnutls_x509_crq_import(crq, &pem, incert_format);
1783
1784         free(pem.data);
1785         if (ret < 0) {
1786                 fprintf(stderr, "import error: %s\n", gnutls_strerror(ret));
1787                 exit(1);
1788         }
1789
1790         print_crq_info(crq, outfile);
1791
1792         gnutls_x509_crq_deinit(crq);
1793 }
1794
1795 static void privkey_info_int(common_info_st * cinfo,
1796                              gnutls_x509_privkey_t key)
1797 {
1798         int ret, key_type;
1799         unsigned int bits = 0;
1800         size_t size;
1801         const char *cprint;
1802
1803         /* Public key algorithm
1804          */
1805         fprintf(outfile, "Public Key Info:\n");
1806         ret = gnutls_x509_privkey_get_pk_algorithm2(key, &bits);
1807         fprintf(outfile, "\tPublic Key Algorithm: ");
1808
1809         key_type = ret;
1810
1811         cprint = gnutls_pk_algorithm_get_name(key_type);
1812         fprintf(outfile, "%s\n", cprint ? cprint : "Unknown");
1813         fprintf(outfile, "\tKey Security Level: %s (%u bits)\n\n",
1814                 gnutls_sec_param_get_name(gnutls_x509_privkey_sec_param
1815                                           (key)), bits);
1816
1817         /* Print the raw public and private keys
1818          */
1819         if (key_type == GNUTLS_PK_RSA) {
1820                 gnutls_datum_t m, e, d, p, q, u, exp1, exp2;
1821
1822                 ret =
1823                     gnutls_x509_privkey_export_rsa_raw2(key, &m, &e, &d,
1824                                                         &p, &q, &u, &exp1,
1825                                                         &exp2);
1826                 if (ret < 0)
1827                         fprintf(stderr,
1828                                 "Error in key RSA data export: %s\n",
1829                                 gnutls_strerror(ret));
1830                 else {
1831                         print_rsa_pkey(outfile, &m, &e, &d, &p, &q, &u,
1832                                        &exp1, &exp2, HAVE_OPT(CPRINT));
1833
1834                         gnutls_free(m.data);
1835                         gnutls_free(e.data);
1836                         gnutls_free(d.data);
1837                         gnutls_free(p.data);
1838                         gnutls_free(q.data);
1839                         gnutls_free(u.data);
1840                         gnutls_free(exp1.data);
1841                         gnutls_free(exp2.data);
1842                 }
1843         } else if (key_type == GNUTLS_PK_DSA) {
1844                 gnutls_datum_t p, q, g, y, x;
1845
1846                 ret =
1847                     gnutls_x509_privkey_export_dsa_raw(key, &p, &q, &g, &y,
1848                                                        &x);
1849                 if (ret < 0)
1850                         fprintf(stderr,
1851                                 "Error in key DSA data export: %s\n",
1852                                 gnutls_strerror(ret));
1853                 else {
1854                         print_dsa_pkey(outfile, &x, &y, &p, &q, &g,
1855                                        HAVE_OPT(CPRINT));
1856
1857                         gnutls_free(x.data);
1858                         gnutls_free(y.data);
1859                         gnutls_free(p.data);
1860                         gnutls_free(q.data);
1861                         gnutls_free(g.data);
1862                 }
1863         } else if (key_type == GNUTLS_PK_EC) {
1864                 gnutls_datum_t y, x, k;
1865                 gnutls_ecc_curve_t curve;
1866
1867                 ret =
1868                     gnutls_x509_privkey_export_ecc_raw(key, &curve, &x, &y,
1869                                                        &k);
1870                 if (ret < 0)
1871                         fprintf(stderr,
1872                                 "Error in key ECC data export: %s\n",
1873                                 gnutls_strerror(ret));
1874                 else {
1875                         print_ecc_pkey(outfile, curve, &k, &x, &y,
1876                                        HAVE_OPT(CPRINT));
1877
1878                         gnutls_free(x.data);
1879                         gnutls_free(y.data);
1880                         gnutls_free(k.data);
1881                 }
1882         }
1883
1884         fprintf(outfile, "\n");
1885
1886         size = lbuffer_size;
1887         if ((ret =
1888              gnutls_x509_privkey_get_key_id(key, 0, lbuffer, &size)) < 0) {
1889                 fprintf(stderr, "Error in key id calculation: %s\n",
1890                         gnutls_strerror(ret));
1891         } else {
1892                 gnutls_datum_t art;
1893
1894                 fprintf(outfile, "Public Key ID: %s\n",
1895                         raw_to_string(lbuffer, size));
1896
1897                 ret =
1898                     gnutls_random_art(GNUTLS_RANDOM_ART_OPENSSH, cprint,
1899                                       bits, lbuffer, size, &art);
1900                 if (ret >= 0) {
1901                         fprintf(outfile, "Public key's random art:\n%s\n",
1902                                 art.data);
1903                         gnutls_free(art.data);
1904                 }
1905         }
1906         fprintf(outfile, "\n");
1907
1908 }
1909
1910 void privkey_info(common_info_st * cinfo)
1911 {
1912         gnutls_x509_privkey_t key;
1913         size_t size;
1914         int ret;
1915         gnutls_datum_t pem;
1916         const char *pass;
1917         unsigned int flags = 0;
1918
1919         size = fread(lbuffer, 1, lbuffer_size - 1, infile);
1920         lbuffer[size] = 0;
1921
1922         gnutls_x509_privkey_init(&key);
1923
1924         pem.data = lbuffer;
1925         pem.size = size;
1926
1927         ret =
1928             gnutls_x509_privkey_import2(key, &pem, incert_format, NULL, GNUTLS_PKCS_PLAIN);
1929
1930         /* If we failed to import the certificate previously try PKCS #8 */
1931         if (ret == GNUTLS_E_DECRYPTION_FAILED) {
1932                 fprintf(stderr, "Encrypted structure detected...\n");
1933
1934                 pkcs8_info_int(&pem, incert_format, 1, outfile, "");
1935
1936                 pass = get_password(cinfo, &flags, 0);
1937
1938                 ret = gnutls_x509_privkey_import2(key, &pem,
1939                                                   incert_format, pass,
1940                                                   flags);
1941         }
1942         if (ret < 0) {
1943                 fprintf(stderr, "import error: %s\n", gnutls_strerror(ret));
1944                 exit(1);
1945         }
1946
1947         if (outcert_format == GNUTLS_X509_FMT_PEM)
1948                 privkey_info_int(cinfo, key);
1949
1950         ret = gnutls_x509_privkey_verify_params(key);
1951         if (ret < 0)
1952                 fprintf(outfile,
1953                         "\n** Private key parameters validation failed **\n\n");
1954
1955         size = lbuffer_size;
1956         ret =
1957             gnutls_x509_privkey_export(key, outcert_format, lbuffer, &size);
1958         if (ret < 0) {
1959                 fprintf(stderr, "export error: %s\n", gnutls_strerror(ret));
1960                 exit(1);
1961         }
1962
1963         fwrite(lbuffer, 1, size, outfile);
1964
1965         gnutls_x509_privkey_deinit(key);
1966 }
1967
1968
1969 /* Generate a PKCS #10 certificate request.
1970  */
1971 void generate_request(common_info_st * cinfo)
1972 {
1973         gnutls_x509_crq_t crq;
1974         gnutls_x509_privkey_t xkey;
1975         gnutls_pubkey_t pubkey;
1976         gnutls_privkey_t pkey;
1977         int ret, ca_status, path_len, pk;
1978         const char *pass;
1979         unsigned int usage = 0;
1980
1981         fprintf(stderr, "Generating a PKCS #10 certificate request...\n");
1982
1983         ret = gnutls_x509_crq_init(&crq);
1984         if (ret < 0) {
1985                 fprintf(stderr, "crq_init: %s\n", gnutls_strerror(ret));
1986                 exit(1);
1987         }
1988
1989
1990         /* Load the private key.
1991          */
1992         pkey = load_private_key(0, cinfo);
1993         if (!pkey) {
1994                 ret = gnutls_privkey_init(&pkey);
1995                 if (ret < 0) {
1996                         fprintf(stderr, "privkey_init: %s\n",
1997                                 gnutls_strerror(ret));
1998                         exit(1);
1999                 }
2000
2001                 xkey = generate_private_key_int(cinfo);
2002
2003                 print_private_key(cinfo, xkey);
2004
2005                 ret =
2006                     gnutls_privkey_import_x509(pkey, xkey,
2007                                                GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
2008                 if (ret < 0) {
2009                         fprintf(stderr, "privkey_import_x509: %s\n",
2010                                 gnutls_strerror(ret));
2011                         exit(1);
2012                 }
2013         }
2014
2015         pubkey = load_public_key_or_import(1, pkey, cinfo);
2016
2017         pk = gnutls_pubkey_get_pk_algorithm(pubkey, NULL);
2018
2019         /* Set the DN.
2020          */
2021         get_dn_crq_set(crq);
2022
2023         get_cn_crq_set(crq);
2024         get_unit_crq_set(crq);
2025         get_organization_crq_set(crq);
2026         get_locality_crq_set(crq);
2027         get_state_crq_set(crq);
2028         get_country_crq_set(crq);
2029
2030         get_dc_set(TYPE_CRQ, crq);
2031         get_uid_crq_set(crq);
2032         get_oid_crq_set(crq);
2033
2034         get_dns_name_set(TYPE_CRQ, crq);
2035         get_uri_set(TYPE_CRQ, crq);
2036         get_ip_addr_set(TYPE_CRQ, crq);
2037         get_email_set(TYPE_CRQ, crq);
2038
2039         pass = get_challenge_pass();
2040
2041         if (pass != NULL && pass[0] != 0) {
2042                 ret = gnutls_x509_crq_set_challenge_password(crq, pass);
2043                 if (ret < 0) {
2044                         fprintf(stderr, "set_pass: %s\n",
2045                                 gnutls_strerror(ret));
2046                         exit(1);
2047                 }
2048         }
2049
2050         if (cinfo->crq_extensions != 0) {
2051                 ca_status = get_ca_status();
2052                 if (ca_status)
2053                         path_len = get_path_len();
2054                 else
2055                         path_len = -1;
2056
2057                 ret =
2058                     gnutls_x509_crq_set_basic_constraints(crq, ca_status,
2059                                                           path_len);
2060                 if (ret < 0) {
2061                         fprintf(stderr, "set_basic_constraints: %s\n",
2062                                 gnutls_strerror(ret));
2063                         exit(1);
2064                 }
2065
2066                 if (pk == GNUTLS_PK_RSA) {
2067                         ret = get_sign_status(1);
2068                         if (ret)
2069                                 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
2070
2071                         /* Only ask for an encryption certificate
2072                          * if it is an RSA one */
2073                         ret = get_encrypt_status(1);
2074                         if (ret)
2075                                 usage |= GNUTLS_KEY_KEY_ENCIPHERMENT;
2076                         else
2077                                 usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
2078                 } else          /* DSA and ECDSA are always signing */
2079                         usage |= GNUTLS_KEY_DIGITAL_SIGNATURE;
2080
2081                 if (ca_status) {
2082                         ret = get_cert_sign_status();
2083                         if (ret)
2084                                 usage |= GNUTLS_KEY_KEY_CERT_SIGN;
2085
2086                         ret = get_crl_sign_status();
2087                         if (ret)
2088                                 usage |= GNUTLS_KEY_CRL_SIGN;
2089
2090                         ret = get_code_sign_status();
2091                         if (ret) {
2092                                 ret = gnutls_x509_crq_set_key_purpose_oid
2093                                     (crq, GNUTLS_KP_CODE_SIGNING, 0);
2094                                 if (ret < 0) {
2095                                         fprintf(stderr, "key_kp: %s\n",
2096                                                 gnutls_strerror(ret));
2097                                         exit(1);
2098                                 }
2099                         }
2100
2101                         ret = get_ocsp_sign_status();
2102                         if (ret) {
2103                                 ret = gnutls_x509_crq_set_key_purpose_oid
2104                                     (crq, GNUTLS_KP_OCSP_SIGNING, 0);
2105                                 if (ret < 0) {
2106                                         fprintf(stderr, "key_kp: %s\n",
2107                                                 gnutls_strerror(ret));
2108                                         exit(1);
2109                                 }
2110                         }
2111
2112                         ret = get_time_stamp_status();
2113                         if (ret) {
2114                                 ret = gnutls_x509_crq_set_key_purpose_oid
2115                                     (crq, GNUTLS_KP_TIME_STAMPING, 0);
2116                                 if (ret < 0) {
2117                                         fprintf(stderr, "key_kp: %s\n",
2118                                                 gnutls_strerror(ret));
2119                                         exit(1);
2120                                 }
2121                         }
2122
2123                         ret = get_ipsec_ike_status();
2124                         if (ret) {
2125                                 ret = gnutls_x509_crq_set_key_purpose_oid
2126                                     (crq, GNUTLS_KP_IPSEC_IKE, 0);
2127                                 if (ret < 0) {
2128                                         fprintf(stderr, "key_kp: %s\n",
2129                                                 gnutls_strerror(ret));
2130                                         exit(1);
2131                                 }
2132                         }
2133                 }
2134
2135                 ret = gnutls_x509_crq_set_key_usage(crq, usage);
2136                 if (ret < 0) {
2137                         fprintf(stderr, "key_usage: %s\n",
2138                                 gnutls_strerror(ret));
2139                         exit(1);
2140                 }
2141
2142                 ret = get_tls_client_status();
2143                 if (ret != 0) {
2144                         ret = gnutls_x509_crq_set_key_purpose_oid
2145                             (crq, GNUTLS_KP_TLS_WWW_CLIENT, 0);
2146                         if (ret < 0) {
2147                                 fprintf(stderr, "key_kp: %s\n",
2148                                         gnutls_strerror(ret));
2149                                 exit(1);
2150                         }
2151                 }
2152
2153                 ret = get_tls_server_status();
2154                 if (ret != 0) {
2155                         ret = gnutls_x509_crq_set_key_purpose_oid
2156                             (crq, GNUTLS_KP_TLS_WWW_SERVER, 0);
2157                         if (ret < 0) {
2158                                 fprintf(stderr, "key_kp: %s\n",
2159                                         gnutls_strerror(ret));
2160                                 exit(1);
2161                         }
2162                 }
2163
2164                 get_key_purpose_set(TYPE_CRQ, crq);
2165         }
2166
2167         ret = gnutls_x509_crq_set_pubkey(crq, pubkey);
2168         if (ret < 0) {
2169                 fprintf(stderr, "set_key: %s\n", gnutls_strerror(ret));
2170                 exit(1);
2171         }
2172
2173         ret =
2174             gnutls_x509_crq_privkey_sign(crq, pkey,
2175                                          get_dig_for_pub(pubkey), 0);
2176         if (ret < 0) {
2177                 fprintf(stderr, "sign: %s\n", gnutls_strerror(ret));
2178                 exit(1);
2179         }
2180
2181         print_crq_info(crq, outfile);
2182
2183         gnutls_x509_crq_deinit(crq);
2184         gnutls_privkey_deinit(pkey);
2185         gnutls_pubkey_deinit(pubkey);
2186
2187 }
2188
2189 static void print_verification_res(FILE * outfile, unsigned int output);
2190
2191 static int detailed_verification(gnutls_x509_crt_t cert,
2192                                  gnutls_x509_crt_t issuer,
2193                                  gnutls_x509_crl_t crl,
2194                                  unsigned int verification_output)
2195 {
2196         char name[512];
2197         char tmp[255];
2198         char issuer_name[512];
2199         size_t name_size;
2200         size_t issuer_name_size;
2201         int ret;
2202
2203         issuer_name_size = sizeof(issuer_name);
2204         ret =
2205             gnutls_x509_crt_get_issuer_dn(cert, issuer_name,
2206                                           &issuer_name_size);
2207         if (ret < 0) {
2208                 fprintf(stderr, "gnutls_x509_crt_get_issuer_dn: %s\n",
2209                         gnutls_strerror(ret));
2210                 exit(1);
2211         }
2212
2213         name_size = sizeof(name);
2214         ret = gnutls_x509_crt_get_dn(cert, name, &name_size);
2215         if (ret < 0) {
2216                 fprintf(stderr, "gnutls_x509_crt_get_dn: %s\n",
2217                         gnutls_strerror(ret));
2218                 exit(1);
2219         }
2220
2221         fprintf(outfile, "\tSubject: %s\n", name);
2222         fprintf(outfile, "\tIssuer: %s\n", issuer_name);
2223
2224         if (issuer != NULL) {
2225                 issuer_name_size = sizeof(issuer_name);
2226                 ret =
2227                     gnutls_x509_crt_get_dn(issuer, issuer_name,
2228                                            &issuer_name_size);
2229                 if (ret < 0) {
2230                         fprintf(stderr,
2231                                 "gnutls_x509_crt_get_issuer_dn: %s\n",
2232                                 gnutls_strerror(ret));
2233                         exit(1);
2234                 }
2235
2236                 fprintf(outfile, "\tChecked against: %s\n", issuer_name);
2237         }
2238
2239         if (crl != NULL) {
2240                 gnutls_datum_t data;
2241
2242                 issuer_name_size = sizeof(issuer_name);
2243                 ret =
2244                     gnutls_x509_crl_get_issuer_dn(crl, issuer_name,
2245                                                   &issuer_name_size);
2246                 if (ret < 0) {
2247                         fprintf(stderr,
2248                                 "gnutls_x509_crl_get_issuer_dn: %s\n",
2249                                 gnutls_strerror(ret));
2250                         exit(1);
2251                 }
2252
2253                 name_size = sizeof(tmp);
2254                 ret =
2255                     gnutls_x509_crl_get_number(crl, tmp, &name_size, NULL);
2256                 if (ret < 0)
2257                         strcpy(name, "unnumbered");
2258                 else {
2259                         data.data = (void *) tmp;
2260                         data.size = name_size;
2261
2262                         name_size = sizeof(name);
2263                         ret = gnutls_hex_encode(&data, name, &name_size);
2264                         if (ret < 0) {
2265                                 fprintf(stderr, "gnutls_hex_encode: %s\n",
2266                                         gnutls_strerror(ret));
2267                                 exit(1);
2268                         }
2269                 }
2270                 fprintf(outfile, "\tChecked against CRL[%s] of: %s\n",
2271                         name, issuer_name);
2272         }
2273
2274         fprintf(outfile, "\tOutput: ");
2275         print_verification_res(outfile, verification_output);
2276
2277         fputs("\n\n", outfile);
2278
2279         return 0;
2280 }
2281
2282 /* Will verify a certificate chain. If no CA certificates
2283  * are provided, then the last certificate in the certificate
2284  * chain is used as a CA.
2285  *
2286  * If @system is non-zero then the system's CA will be used.
2287  */
2288 static int
2289 _verify_x509_mem(const void *cert, int cert_size, const void *ca,
2290                  int ca_size, unsigned system, const char *purpose,
2291                  const char *hostname)
2292 {
2293         int ret;
2294         gnutls_datum_t tmp;
2295         gnutls_x509_crt_t *x509_cert_list = NULL;
2296         gnutls_x509_crt_t *x509_ca_list = NULL;
2297         gnutls_x509_crl_t *x509_crl_list = NULL;
2298         unsigned int x509_ncerts, x509_ncrls = 0, x509_ncas = 0;
2299         gnutls_x509_trust_list_t list;
2300         unsigned int output;
2301
2302         ret = gnutls_x509_trust_list_init(&list, 0);
2303         if (ret < 0) {
2304                 fprintf(stderr, "gnutls_x509_trust_list_init: %s\n",
2305                         gnutls_strerror(ret));
2306                 exit(1);
2307         }
2308
2309         if (system != 0) {
2310                 ret = gnutls_x509_trust_list_add_system_trust(list, 0, 0);
2311                 if (ret < 0) {
2312                         fprintf(stderr, "Error loading system trust: %s\n",
2313                                 gnutls_strerror(ret));
2314                         exit(1);
2315                 }
2316                 fprintf(stderr, "Loaded system trust (%d CAs available)\n", ret);
2317
2318                 x509_ncas = ret;
2319
2320                 tmp.data = (void *) cert;
2321                 tmp.size = cert_size;
2322
2323                 /* ignore errors. CRLs might not be given */
2324                 ret =
2325                     gnutls_x509_crt_list_import2(&x509_cert_list,
2326                                                  &x509_ncerts, &tmp,
2327                                                  GNUTLS_X509_FMT_PEM, 0);
2328                 if (ret < 0 || x509_ncerts < 1) {
2329                         fprintf(stderr, "error parsing CRTs: %s\n",
2330                                 gnutls_strerror(ret));
2331                         exit(1);
2332                 }
2333
2334         } else {
2335                 if (ca == NULL) {
2336                         tmp.data = (void *) cert;
2337                         tmp.size = cert_size;
2338                 } else {
2339                         tmp.data = (void *) ca;
2340                         tmp.size = ca_size;
2341
2342                         /* Load CAs */
2343                         ret =
2344                             gnutls_x509_crt_list_import2(&x509_ca_list,
2345                                                          &x509_ncas, &tmp,
2346                                                          GNUTLS_X509_FMT_PEM,
2347                                                          0);
2348                         if (ret < 0 || x509_ncas < 1) {
2349                                 fprintf(stderr, "error parsing CAs: %s\n",
2350                                         gnutls_strerror(ret));
2351                                 exit(1);
2352                         }
2353                 }
2354
2355                 ret =
2356                     gnutls_x509_crl_list_import2(&x509_crl_list,
2357                                                  &x509_ncrls, &tmp,
2358                                                  GNUTLS_X509_FMT_PEM, 0);
2359                 if (ret < 0) {
2360                         x509_crl_list = NULL;
2361                         x509_ncrls = 0;
2362                 }
2363
2364
2365                 tmp.data = (void *) cert;
2366                 tmp.size = cert_size;
2367
2368                 /* ignore errors. CRLs might not be given */
2369                 ret =
2370                     gnutls_x509_crt_list_import2(&x509_cert_list,
2371                                                  &x509_ncerts, &tmp,
2372                                                  GNUTLS_X509_FMT_PEM, 0);
2373                 if (ret < 0 || x509_ncerts < 1) {
2374                         fprintf(stderr, "error parsing CRTs: %s\n",
2375                                 gnutls_strerror(ret));
2376                         exit(1);
2377                 }
2378
2379                 if (ca == NULL) {
2380                         x509_ca_list = &x509_cert_list[x509_ncerts - 1];
2381                         x509_ncas = 1;
2382                 }
2383
2384                 ret =
2385                     gnutls_x509_trust_list_add_cas(list, x509_ca_list,
2386                                                    x509_ncas, 0);
2387                 if (ret < 0) {
2388                         fprintf(stderr, "gnutls_x509_trust_add_cas: %s\n",
2389                                 gnutls_strerror(ret));
2390                         exit(1);
2391                 }
2392
2393                 ret =
2394                     gnutls_x509_trust_list_add_crls(list, x509_crl_list,
2395                                                     x509_ncrls, 0, 0);
2396                 if (ret < 0) {
2397                         fprintf(stderr, "gnutls_x509_trust_add_crls: %s\n",
2398                                 gnutls_strerror(ret));
2399                         exit(1);
2400                 }
2401
2402                 gnutls_free(x509_crl_list);
2403         }
2404
2405         fprintf(stdout, "Loaded %d certificates, %d CAs and %d CRLs\n\n",
2406                 x509_ncerts, x509_ncas, x509_ncrls);
2407
2408         if (purpose || hostname) {
2409                 gnutls_typed_vdata_st vdata[2];
2410                 unsigned vdata_size = 0;
2411
2412                 if (purpose) {
2413                         vdata[vdata_size].type = GNUTLS_DT_KEY_PURPOSE_OID;
2414                         vdata[vdata_size].data = (void*)purpose;
2415                         vdata[vdata_size].size = strlen(purpose);
2416                         vdata_size++;
2417                 }
2418
2419                 if (hostname) {
2420                         vdata[vdata_size].type = GNUTLS_DT_DNS_HOSTNAME;
2421                         vdata[vdata_size].data = (void*)hostname;
2422                         vdata[vdata_size].size = strlen(hostname);
2423                         vdata_size++;
2424                 }
2425
2426                 ret =
2427                     gnutls_x509_trust_list_verify_crt2(list, x509_cert_list,
2428                                                        x509_ncerts,
2429                                                        vdata,
2430                                                        vdata_size,
2431                                                        GNUTLS_VERIFY_DO_NOT_ALLOW_SAME,
2432                                                        &output,
2433                                                        detailed_verification);
2434         } else { 
2435                 ret =
2436                     gnutls_x509_trust_list_verify_crt(list, x509_cert_list,
2437                                                       x509_ncerts,
2438                                                       GNUTLS_VERIFY_DO_NOT_ALLOW_SAME,
2439                                                       &output,
2440                                                       detailed_verification);
2441         }
2442         if (ret < 0) {
2443                 fprintf(stderr, "gnutls_x509_trusted_list_verify_crt: %s\n",
2444                         gnutls_strerror(ret));
2445                 exit(1);
2446         }
2447
2448         fprintf(outfile, "Chain verification output: ");
2449         print_verification_res(outfile, output);
2450
2451         fprintf(outfile, "\n\n");
2452
2453         gnutls_free(x509_cert_list);
2454         gnutls_x509_trust_list_deinit(list, 1);
2455
2456         if (output != 0)
2457                 exit(EXIT_FAILURE);
2458
2459         return 0;
2460 }
2461
2462 static void print_verification_res(FILE * out, unsigned int output)
2463 {
2464         gnutls_datum_t pout;
2465         int ret;
2466
2467         if (output) {
2468                 fprintf(out, "Not verified.");
2469         } else {
2470                 fprintf(out, "Verified.");
2471         }
2472
2473         ret =
2474             gnutls_certificate_verification_status_print(output,
2475                                                          GNUTLS_CRT_X509,
2476                                                          &pout, 0);
2477         if (ret < 0) {
2478                 fprintf(stderr, "error: %s\n", gnutls_strerror(ret));
2479                 exit(EXIT_FAILURE);
2480         }
2481
2482         fprintf(out, " %s", pout.data);
2483         gnutls_free(pout.data);
2484 }
2485
2486 static void verify_chain(void)
2487 {
2488         char *buf;
2489         size_t size;
2490
2491         buf = (void *) fread_file(infile, &size);
2492         if (buf == NULL) {
2493                 fprintf(stderr, "reading chain");
2494                 exit(1);
2495         }
2496
2497         buf[size] = 0;
2498
2499         _verify_x509_mem(buf, size, NULL, 0, 0, OPT_ARG(PURPOSE), OPT_ARG(HOSTNAME));
2500
2501 }
2502
2503 static void verify_certificate(common_info_st * cinfo)
2504 {
2505         char *cert;
2506         char *cas = NULL;
2507         size_t cert_size, ca_size = 0;
2508         FILE *ca_file;
2509
2510         cert = (void *) fread_file(infile, &cert_size);
2511         if (cert == NULL) {
2512                 fprintf(stderr, "reading certificate chain");
2513                 exit(1);
2514         }
2515
2516         if (cinfo->ca != NULL) {
2517                 ca_file = fopen(cinfo->ca, "r");
2518                 if (ca_file == NULL) {
2519                         fprintf(stderr, "Could not open %s\n", cinfo->ca);
2520                         exit(1);
2521                 }
2522
2523                 cert[cert_size] = 0;
2524
2525                 cas = (void *) fread_file(ca_file, &ca_size);
2526                 if (cas == NULL) {
2527                         fprintf(stderr, "reading CA list");
2528                         exit(1);
2529                 }
2530
2531                 cas[ca_size] = 0;
2532                 fclose(ca_file);
2533         }
2534
2535         _verify_x509_mem(cert, cert_size, cas, ca_size,
2536                          (cinfo->ca != NULL) ? 0 : 1, OPT_ARG(PURPOSE), OPT_ARG(HOSTNAME));
2537
2538
2539 }
2540
2541 void verify_crl(common_info_st * cinfo)
2542 {
2543         size_t size, dn_size;
2544         char dn[128];
2545         unsigned int output;
2546         int ret;
2547         gnutls_datum_t pem, pout;
2548         gnutls_x509_crl_t crl;
2549         gnutls_x509_crt_t issuer;
2550
2551         issuer = load_ca_cert(1, cinfo);
2552
2553         fprintf(outfile, "\nCA certificate:\n");
2554
2555         dn_size = sizeof(dn);
2556         ret = gnutls_x509_crt_get_dn(issuer, dn, &dn_size);
2557         if (ret < 0) {
2558                 fprintf(stderr, "crt_get_dn: %s\n", gnutls_strerror(ret));
2559                 exit(1);
2560         }
2561
2562         fprintf(outfile, "\tSubject: %s\n\n", dn);
2563
2564         ret = gnutls_x509_crl_init(&crl);
2565         if (ret < 0) {
2566                 fprintf(stderr, "crl_init: %s\n", gnutls_strerror(ret));
2567                 exit(1);
2568         }
2569
2570         pem.data = (void *) fread_file(infile, &size);
2571         pem.size = size;
2572
2573         ret = gnutls_x509_crl_import(crl, &pem, incert_format);
2574         free(pem.data);
2575         if (ret < 0) {
2576                 fprintf(stderr, "import error: %s\n", gnutls_strerror(ret));
2577                 exit(1);
2578         }
2579
2580         print_crl_info(crl, outfile);
2581
2582         fprintf(outfile, "Verification output: ");
2583         ret = gnutls_x509_crl_verify(crl, &issuer, 1, 0, &output);
2584         if (ret < 0) {
2585                 fprintf(stderr, "verification error: %s\n",
2586                         gnutls_strerror(ret));
2587                 exit(1);
2588         }
2589
2590         if (output) {
2591                 fprintf(outfile, "Not verified. ");
2592         } else {
2593                 fprintf(outfile, "Verified.");
2594         }
2595
2596         ret =
2597             gnutls_certificate_verification_status_print(output,
2598                                                          GNUTLS_CRT_X509,
2599                                                          &pout, 0);
2600         if (ret < 0) {
2601                 fprintf(stderr, "error: %s\n", gnutls_strerror(ret));
2602                 exit(EXIT_FAILURE);
2603         }
2604
2605         fprintf(outfile, " %s", pout.data);
2606         gnutls_free(pout.data);
2607
2608         fprintf(outfile, "\n");
2609 }
2610
2611
2612
2613 void generate_pkcs8(common_info_st * cinfo)
2614 {
2615         gnutls_x509_privkey_t key;
2616         int result;
2617         size_t size;
2618         unsigned int flags = 0;
2619         const char *password;
2620
2621         fprintf(stderr, "Generating a PKCS #8 key structure...\n");
2622
2623         key = load_x509_private_key(1, cinfo);
2624
2625         password = get_password(cinfo, &flags, 1);
2626
2627         flags |= cipher_to_flags(cinfo->pkcs_cipher);
2628
2629         size = lbuffer_size;
2630         result =
2631             gnutls_x509_privkey_export_pkcs8(key, outcert_format,
2632                                              password, flags, lbuffer,
2633                                              &size);
2634
2635         if (result < 0) {
2636                 fprintf(stderr, "key_export: %s\n", gnutls_strerror(result));
2637                 exit(1);
2638         }
2639
2640         fwrite(lbuffer, 1, size, outfile);
2641
2642 }
2643
2644
2645 #include <gnutls/pkcs12.h>
2646 #include <unistd.h>
2647
2648 void generate_pkcs12(common_info_st * cinfo)
2649 {
2650         gnutls_pkcs12_t pkcs12;
2651         gnutls_x509_crt_t *crts, ca_crt;
2652         gnutls_x509_privkey_t *keys;
2653         int result;
2654         size_t size;
2655         gnutls_datum_t data;
2656         const char *pass;
2657         const char *name;
2658         unsigned int flags = 0, i;
2659         gnutls_datum_t key_id;
2660         unsigned char _key_id[32];
2661         int indx;
2662         size_t ncrts;
2663         size_t nkeys;
2664
2665         fprintf(stderr, "Generating a PKCS #12 structure...\n");
2666
2667         keys = load_privkey_list(0, &nkeys, cinfo);
2668         crts = load_cert_list(0, &ncrts, cinfo);
2669         ca_crt = load_ca_cert(0, cinfo);
2670
2671         if (HAVE_OPT(P12_NAME)) {
2672                 name = OPT_ARG(P12_NAME);
2673         } else {
2674                 name = get_pkcs12_key_name();
2675         }
2676
2677         result = gnutls_pkcs12_init(&pkcs12);
2678         if (result < 0) {
2679                 fprintf(stderr, "pkcs12_init: %s\n",
2680                         gnutls_strerror(result));
2681                 exit(1);
2682         }
2683
2684         pass = get_password(cinfo, &flags, 1);
2685         flags |= cipher_to_flags(cinfo->pkcs_cipher);
2686
2687         for (i = 0; i < ncrts; i++) {
2688                 gnutls_pkcs12_bag_t bag;
2689
2690                 result = gnutls_pkcs12_bag_init(&bag);
2691                 if (result < 0) {
2692                         fprintf(stderr, "bag_init: %s\n",
2693                                 gnutls_strerror(result));
2694                         exit(1);
2695                 }
2696
2697                 result = gnutls_pkcs12_bag_set_crt(bag, crts[i]);
2698                 if (result < 0) {
2699                         fprintf(stderr, "set_crt[%d]: %s\n", i,
2700                                 gnutls_strerror(result));
2701                         exit(1);
2702                 }
2703
2704                 indx = result;
2705
2706                 if (i == 0) {   /* only the first certificate gets the friendly name */
2707                         result =
2708                             gnutls_pkcs12_bag_set_friendly_name(bag, indx,
2709                                                                 name);
2710                         if (result < 0) {
2711                                 fprintf(stderr,
2712                                         "bag_set_friendly_name: %s\n",
2713                                         gnutls_strerror(result));
2714                                 exit(1);
2715                         }
2716                 }
2717
2718                 size = sizeof(_key_id);
2719                 result =
2720                     gnutls_x509_crt_get_key_id(crts[i], 0, _key_id, &size);
2721                 if (result < 0) {
2722                         fprintf(stderr, "key_id[%d]: %s\n", i,
2723                                 gnutls_strerror(result));
2724                         exit(1);
2725                 }
2726
2727                 key_id.data = _key_id;
2728                 key_id.size = size;
2729
2730                 result = gnutls_pkcs12_bag_set_key_id(bag, indx, &key_id);
2731                 if (result < 0) {
2732                         fprintf(stderr, "bag_set_key_id: %s\n",
2733                                 gnutls_strerror(result));
2734                         exit(1);
2735                 }
2736
2737                 result = gnutls_pkcs12_bag_encrypt(bag, pass, flags);
2738                 if (result < 0) {
2739                         fprintf(stderr, "bag_encrypt: %s\n",
2740                                 gnutls_strerror(result));
2741                         exit(1);
2742                 }
2743
2744                 result = gnutls_pkcs12_set_bag(pkcs12, bag);
2745                 if (result < 0) {
2746                         fprintf(stderr, "set_bag: %s\n",
2747                                 gnutls_strerror(result));
2748                         exit(1);
2749                 }
2750         }
2751
2752         /* Add the ca cert, if any */
2753         if (ca_crt) {
2754                 gnutls_pkcs12_bag_t bag;
2755
2756                 result = gnutls_pkcs12_bag_init(&bag);
2757                 if (result < 0) {
2758                         fprintf(stderr, "bag_init: %s\n",
2759                                 gnutls_strerror(result));
2760                         exit(1);
2761                 }
2762
2763                 result = gnutls_pkcs12_bag_set_crt(bag, ca_crt);
2764                 if (result < 0) {