__gaa_helpsingle('p', "generate-privkey", "", "Generate a private key.");
__gaa_helpsingle('q', "generate-request", "", "Generate a PKCS #10 certificate request.");
__gaa_helpsingle('e', "verify-chain", "", "Verify a PEM encoded certificate chain. The last certificate in the chain must be a self signed one.");
+ __gaa_helpsingle(0, "verify", "", "Verify a PEM encoded certificate chain. CA certificates must be loaded with --load-ca-certificate.");
__gaa_helpsingle(0, "verify-crl", "", "Verify a CRL.");
__gaa_helpsingle(0, "generate-dh-params", "", "Generate PKCS #3 encoded Diffie-Hellman parameters.");
__gaa_helpsingle(0, "get-dh-params", "", "Get the included PKCS #3 encoded Diffie-Hellman parameters.");
struct _gaainfo
{
-#line 140 "certtool.gaa"
+#line 142 "certtool.gaa"
int debug;
-#line 137 "certtool.gaa"
+#line 139 "certtool.gaa"
char *pkcs_cipher;
-#line 134 "certtool.gaa"
+#line 136 "certtool.gaa"
char *template;
-#line 131 "certtool.gaa"
+#line 133 "certtool.gaa"
char *infile;
-#line 128 "certtool.gaa"
+#line 130 "certtool.gaa"
char *outfile;
-#line 125 "certtool.gaa"
+#line 127 "certtool.gaa"
int quick_random;
-#line 122 "certtool.gaa"
+#line 124 "certtool.gaa"
char* sec_param;
-#line 119 "certtool.gaa"
+#line 121 "certtool.gaa"
int bits;
-#line 115 "certtool.gaa"
+#line 117 "certtool.gaa"
int outcert_format;
-#line 111 "certtool.gaa"
+#line 113 "certtool.gaa"
int incert_format;
-#line 108 "certtool.gaa"
+#line 110 "certtool.gaa"
int export;
-#line 105 "certtool.gaa"
+#line 107 "certtool.gaa"
char *hash;
-#line 102 "certtool.gaa"
+#line 104 "certtool.gaa"
int dsa;
-#line 99 "certtool.gaa"
+#line 101 "certtool.gaa"
int pkcs8;
-#line 92 "certtool.gaa"
+#line 94 "certtool.gaa"
int v1_cert;
-#line 89 "certtool.gaa"
+#line 91 "certtool.gaa"
int fix_key;
-#line 72 "certtool.gaa"
+#line 74 "certtool.gaa"
int crq_extensions;
-#line 57 "certtool.gaa"
+#line 59 "certtool.gaa"
char *pass;
-#line 54 "certtool.gaa"
+#line 56 "certtool.gaa"
char *ca;
-#line 51 "certtool.gaa"
+#line 53 "certtool.gaa"
char *ca_privkey;
-#line 48 "certtool.gaa"
+#line 50 "certtool.gaa"
char *cert;
-#line 45 "certtool.gaa"
+#line 47 "certtool.gaa"
char *request;
-#line 42 "certtool.gaa"
+#line 44 "certtool.gaa"
char *pubkey;
-#line 39 "certtool.gaa"
+#line 41 "certtool.gaa"
char *privkey;
#line 17 "certtool.gaa"
int action;
#define GAA_MULTIPLE_OPTION 3
#define GAA_REST 0
-#define GAA_NB_OPTION 53
+#define GAA_NB_OPTION 54
#define GAAOPTID_version 1
#define GAAOPTID_help 2
#define GAAOPTID_debug 3
#define GAAOPTID_get_dh_params 43
#define GAAOPTID_generate_dh_params 44
#define GAAOPTID_verify_crl 45
-#define GAAOPTID_verify_chain 46
-#define GAAOPTID_generate_request 47
-#define GAAOPTID_generate_privkey 48
-#define GAAOPTID_update_certificate 49
-#define GAAOPTID_generate_crl 50
-#define GAAOPTID_generate_proxy 51
-#define GAAOPTID_generate_certificate 52
-#define GAAOPTID_generate_self_signed 53
+#define GAAOPTID_verify 46
+#define GAAOPTID_verify_chain 47
+#define GAAOPTID_generate_request 48
+#define GAAOPTID_generate_privkey 49
+#define GAAOPTID_update_certificate 50
+#define GAAOPTID_generate_crl 51
+#define GAAOPTID_generate_proxy 52
+#define GAAOPTID_generate_certificate 53
+#define GAAOPTID_generate_self_signed 54
#line 168 "gaa.skel"
GAA_CHECK1STR("", GAAOPTID_get_dh_params);
GAA_CHECK1STR("", GAAOPTID_generate_dh_params);
GAA_CHECK1STR("", GAAOPTID_verify_crl);
+ GAA_CHECK1STR("", GAAOPTID_verify);
GAA_CHECK1STR("e", GAAOPTID_verify_chain);
GAA_CHECK1STR("q", GAAOPTID_generate_request);
GAA_CHECK1STR("p", GAAOPTID_generate_privkey);
GAA_CHECKSTR("get-dh-params", GAAOPTID_get_dh_params);
GAA_CHECKSTR("generate-dh-params", GAAOPTID_generate_dh_params);
GAA_CHECKSTR("verify-crl", GAAOPTID_verify_crl);
+ GAA_CHECKSTR("verify", GAAOPTID_verify);
GAA_CHECKSTR("verify-chain", GAAOPTID_verify_chain);
GAA_CHECKSTR("generate-request", GAAOPTID_generate_request);
GAA_CHECKSTR("generate-privkey", GAAOPTID_generate_privkey);
{
case GAAOPTID_version:
OK = 0;
-#line 145 "certtool.gaa"
+#line 147 "certtool.gaa"
{ certtool_version(); exit(0); ;};
return GAA_OK;
break;
case GAAOPTID_help:
OK = 0;
-#line 143 "certtool.gaa"
+#line 145 "certtool.gaa"
{ gaa_help(); exit(0); ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_debug.arg1, gaa_getint, GAATMP_debug.size1);
gaa_index++;
-#line 141 "certtool.gaa"
+#line 143 "certtool.gaa"
{ gaaval->debug = GAATMP_debug.arg1 ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_pkcs_cipher.arg1, gaa_getstr, GAATMP_pkcs_cipher.size1);
gaa_index++;
-#line 138 "certtool.gaa"
+#line 140 "certtool.gaa"
{ gaaval->pkcs_cipher = GAATMP_pkcs_cipher.arg1 ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_template.arg1, gaa_getstr, GAATMP_template.size1);
gaa_index++;
-#line 135 "certtool.gaa"
+#line 137 "certtool.gaa"
{ gaaval->template = GAATMP_template.arg1 ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_infile.arg1, gaa_getstr, GAATMP_infile.size1);
gaa_index++;
-#line 132 "certtool.gaa"
+#line 134 "certtool.gaa"
{ gaaval->infile = GAATMP_infile.arg1 ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_outfile.arg1, gaa_getstr, GAATMP_outfile.size1);
gaa_index++;
-#line 129 "certtool.gaa"
+#line 131 "certtool.gaa"
{ gaaval->outfile = GAATMP_outfile.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_disable_quick_random:
OK = 0;
-#line 126 "certtool.gaa"
+#line 128 "certtool.gaa"
{ gaaval->quick_random = 0; ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_sec_param.arg1, gaa_getstr, GAATMP_sec_param.size1);
gaa_index++;
-#line 123 "certtool.gaa"
+#line 125 "certtool.gaa"
{ gaaval->sec_param = GAATMP_sec_param.arg1 ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_bits.arg1, gaa_getint, GAATMP_bits.size1);
gaa_index++;
-#line 120 "certtool.gaa"
+#line 122 "certtool.gaa"
{ gaaval->bits = GAATMP_bits.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_outraw:
OK = 0;
-#line 117 "certtool.gaa"
+#line 119 "certtool.gaa"
{ gaaval->outcert_format=1 ;};
return GAA_OK;
break;
case GAAOPTID_outder:
OK = 0;
-#line 116 "certtool.gaa"
+#line 118 "certtool.gaa"
{ gaaval->outcert_format=1 ;};
return GAA_OK;
break;
case GAAOPTID_inraw:
OK = 0;
-#line 113 "certtool.gaa"
+#line 115 "certtool.gaa"
{ gaaval->incert_format=1 ;};
return GAA_OK;
break;
case GAAOPTID_inder:
OK = 0;
-#line 112 "certtool.gaa"
+#line 114 "certtool.gaa"
{ gaaval->incert_format=1 ;};
return GAA_OK;
break;
case GAAOPTID_export_ciphers:
OK = 0;
-#line 109 "certtool.gaa"
+#line 111 "certtool.gaa"
{ gaaval->export=1 ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_hash.arg1, gaa_getstr, GAATMP_hash.size1);
gaa_index++;
-#line 106 "certtool.gaa"
+#line 108 "certtool.gaa"
{ gaaval->hash = GAATMP_hash.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_dsa:
OK = 0;
-#line 103 "certtool.gaa"
+#line 105 "certtool.gaa"
{ gaaval->dsa=1 ;};
return GAA_OK;
break;
case GAAOPTID_pkcs8:
OK = 0;
-#line 100 "certtool.gaa"
+#line 102 "certtool.gaa"
{ gaaval->pkcs8=1 ;};
return GAA_OK;
break;
case GAAOPTID_to_p8:
OK = 0;
-#line 97 "certtool.gaa"
+#line 99 "certtool.gaa"
{ gaaval->action = ACTION_GENERATE_PKCS8; ;};
return GAA_OK;
break;
case GAAOPTID_to_p12:
OK = 0;
-#line 95 "certtool.gaa"
+#line 97 "certtool.gaa"
{ gaaval->action = ACTION_TO_PKCS12; ;};
return GAA_OK;
break;
case GAAOPTID_v1:
OK = 0;
-#line 93 "certtool.gaa"
+#line 95 "certtool.gaa"
{ gaaval->v1_cert = 1; ;};
return GAA_OK;
break;
case GAAOPTID_fix_key:
OK = 0;
-#line 90 "certtool.gaa"
+#line 92 "certtool.gaa"
{ gaaval->privkey_op=1; gaaval->fix_key = 1; ;};
return GAA_OK;
break;
case GAAOPTID_pubkey_info:
OK = 0;
-#line 87 "certtool.gaa"
+#line 89 "certtool.gaa"
{ gaaval->action = ACTION_PUBKEY_INFO; ;};
return GAA_OK;
break;
case GAAOPTID_pgp_key_info:
OK = 0;
-#line 85 "certtool.gaa"
+#line 87 "certtool.gaa"
{ gaaval->privkey_op=1; gaaval->action = ACTION_PGP_PRIVKEY_INFO; ;};
return GAA_OK;
break;
case GAAOPTID_key_info:
OK = 0;
-#line 83 "certtool.gaa"
+#line 85 "certtool.gaa"
{ gaaval->privkey_op=1; gaaval->action = ACTION_PRIVKEY_INFO; ;};
return GAA_OK;
break;
case GAAOPTID_smime_to_p7:
OK = 0;
-#line 79 "certtool.gaa"
+#line 81 "certtool.gaa"
{ gaaval->action = ACTION_SMIME_TO_P7; ;};
return GAA_OK;
break;
case GAAOPTID_p7_info:
OK = 0;
-#line 77 "certtool.gaa"
+#line 79 "certtool.gaa"
{ gaaval->action = ACTION_P7_INFO; ;};
return GAA_OK;
break;
case GAAOPTID_p12_info:
OK = 0;
-#line 75 "certtool.gaa"
+#line 77 "certtool.gaa"
{ gaaval->action = ACTION_PKCS12_INFO; ;};
return GAA_OK;
break;
case GAAOPTID_no_crq_extensions:
OK = 0;
-#line 73 "certtool.gaa"
+#line 75 "certtool.gaa"
{ gaaval->crq_extensions = 0; ;};
return GAA_OK;
break;
case GAAOPTID_crq_info:
OK = 0;
-#line 70 "certtool.gaa"
+#line 72 "certtool.gaa"
{ gaaval->action = ACTION_REQUEST; ;};
return GAA_OK;
break;
case GAAOPTID_crl_info:
OK = 0;
-#line 68 "certtool.gaa"
+#line 70 "certtool.gaa"
{ gaaval->action = ACTION_CRL_INFO; ;};
return GAA_OK;
break;
case GAAOPTID_pgp_ring_info:
OK = 0;
-#line 66 "certtool.gaa"
+#line 68 "certtool.gaa"
{ gaaval->action = ACTION_RING_INFO; ;};
return GAA_OK;
break;
case GAAOPTID_pgp_certificate_info:
OK = 0;
-#line 64 "certtool.gaa"
+#line 66 "certtool.gaa"
{ gaaval->action = ACTION_PGP_INFO; ;};
return GAA_OK;
break;
case GAAOPTID_certificate_pubkey:
OK = 0;
-#line 62 "certtool.gaa"
+#line 64 "certtool.gaa"
{ gaaval->action = ACTION_CERT_PUBKEY; ;};
return GAA_OK;
break;
case GAAOPTID_certificate_info:
OK = 0;
-#line 60 "certtool.gaa"
+#line 62 "certtool.gaa"
{ gaaval->action = ACTION_CERT_INFO; ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_password.arg1, gaa_getstr, GAATMP_password.size1);
gaa_index++;
-#line 58 "certtool.gaa"
+#line 60 "certtool.gaa"
{ gaaval->pass = GAATMP_password.arg1 ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_load_ca_certificate.arg1, gaa_getstr, GAATMP_load_ca_certificate.size1);
gaa_index++;
-#line 55 "certtool.gaa"
+#line 57 "certtool.gaa"
{ gaaval->ca = GAATMP_load_ca_certificate.arg1 ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_load_ca_privkey.arg1, gaa_getstr, GAATMP_load_ca_privkey.size1);
gaa_index++;
-#line 52 "certtool.gaa"
+#line 54 "certtool.gaa"
{ gaaval->ca_privkey = GAATMP_load_ca_privkey.arg1 ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_load_certificate.arg1, gaa_getstr, GAATMP_load_certificate.size1);
gaa_index++;
-#line 49 "certtool.gaa"
+#line 51 "certtool.gaa"
{ gaaval->cert = GAATMP_load_certificate.arg1 ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_load_request.arg1, gaa_getstr, GAATMP_load_request.size1);
gaa_index++;
-#line 46 "certtool.gaa"
+#line 48 "certtool.gaa"
{ gaaval->request = GAATMP_load_request.arg1 ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_load_pubkey.arg1, gaa_getstr, GAATMP_load_pubkey.size1);
gaa_index++;
-#line 43 "certtool.gaa"
+#line 45 "certtool.gaa"
{ gaaval->pubkey = GAATMP_load_pubkey.arg1 ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_load_privkey.arg1, gaa_getstr, GAATMP_load_privkey.size1);
gaa_index++;
-#line 40 "certtool.gaa"
+#line 42 "certtool.gaa"
{ gaaval->privkey = GAATMP_load_privkey.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_get_dh_params:
OK = 0;
-#line 37 "certtool.gaa"
+#line 39 "certtool.gaa"
{ gaaval->action=ACTION_GET_DH; ;};
return GAA_OK;
break;
case GAAOPTID_generate_dh_params:
OK = 0;
-#line 36 "certtool.gaa"
+#line 38 "certtool.gaa"
{ gaaval->action=ACTION_GENERATE_DH; ;};
return GAA_OK;
break;
case GAAOPTID_verify_crl:
OK = 0;
-#line 34 "certtool.gaa"
+#line 36 "certtool.gaa"
{ gaaval->action=ACTION_VERIFY_CRL; ;};
+ return GAA_OK;
+ break;
+ case GAAOPTID_verify:
+ OK = 0;
+#line 34 "certtool.gaa"
+{ gaaval->action=ACTION_VERIFY; ;};
+
return GAA_OK;
break;
case GAAOPTID_verify_chain:
if(inited == 0)
{
-#line 147 "certtool.gaa"
+#line 149 "certtool.gaa"
{ gaaval->bits = 0; gaaval->pkcs8 = 0; gaaval->privkey = NULL; gaaval->ca=NULL; gaaval->ca_privkey = NULL;
gaaval->debug=1; gaaval->request = NULL; gaaval->infile = NULL; gaaval->outfile = NULL; gaaval->cert = NULL;
gaaval->incert_format = 0; gaaval->outcert_format = 0; gaaval->action=-1; gaaval->pass = NULL; gaaval->v1_cert = 0;
void pkcs12_info (void);
void generate_pkcs12 (common_info_st *);
void generate_pkcs8 (common_info_st *);
-void verify_chain (void);
+static void verify_chain (void);
void verify_crl (common_info_st * cinfo);
void pubkey_info (gnutls_x509_crt crt, common_info_st *);
void pgp_privkey_info (void);
void generate_request (common_info_st *);
static void print_certificate_info (gnutls_x509_crt_t crt, FILE * out,
unsigned int all);
+static void verify_certificate (common_info_st * cinfo);
static void print_hex_datum (gnutls_datum_t * dat);
case ACTION_VERIFY_CHAIN:
verify_chain ();
break;
+ case ACTION_VERIFY:
+ verify_certificate (&cinfo);
+ break;
case ACTION_PRIVKEY_INFO:
privkey_info ();
break;
return 0;
}
+/* Will verify a certificate chain. If no CA certificates
+ * are provided, then the last certificate in the certificate
+ * chain is used as a CA.
+ */
static int
-_verify_x509_mem (const void *cert, int cert_size)
+_verify_x509_mem (const void *cert, int cert_size, const void* ca, int ca_size)
{
int ret;
gnutls_datum_t tmp;
gnutls_x509_crt_t *x509_cert_list = NULL;
+ gnutls_x509_crt_t *x509_ca_list = NULL;
gnutls_x509_crl_t *x509_crl_list = NULL;
- unsigned int x509_ncerts, x509_ncrls = 0;
+ unsigned int x509_ncerts, x509_ncrls = 0, x509_ncas = 0;
gnutls_x509_trust_list_t list;
unsigned int output;
- tmp.data = (void*)cert;
- tmp.size = cert_size;
+ ret = gnutls_x509_trust_list_init(&list, 0);
+ if (ret < 0)
+ error (EXIT_FAILURE, 0, "gnutls_x509_trust_list_init: %s",
+ gnutls_strerror (ret));
+
+ if (ca == NULL)
+ {
+ tmp.data = (void*)cert;
+ tmp.size = cert_size;
+ }
+ else
+ {
+ tmp.data = (void*)ca;
+ tmp.size = ca_size;
+
+ /* Load CAs */
+ ret = gnutls_x509_crt_list_import2( &x509_ca_list, &x509_ncas, &tmp,
+ GNUTLS_X509_FMT_PEM, 0);
+ if (ret < 0 || x509_ncas < 1)
+ error (EXIT_FAILURE, 0, "error parsing CAs: %s",
+ gnutls_strerror (ret));
+ }
ret = gnutls_x509_crl_list_import2( &x509_crl_list, &x509_ncrls, &tmp,
GNUTLS_X509_FMT_PEM, 0);
x509_ncrls = 0;
}
- /* ignore errors. CRL might not be given */
+ tmp.data = (void*)cert;
+ tmp.size = cert_size;
+ /* ignore errors. CRLs might not be given */
ret = gnutls_x509_crt_list_import2( &x509_cert_list, &x509_ncerts, &tmp,
GNUTLS_X509_FMT_PEM, 0);
if (ret < 0 || x509_ncerts < 1)
error (EXIT_FAILURE, 0, "error parsing CRTs: %s",
gnutls_strerror (ret));
- fprintf(stdout, "Loaded %d certificates and %d CRLs\n\n", x509_ncerts, x509_ncrls);
+ if (ca == NULL)
+ {
+ x509_ca_list = &x509_cert_list[x509_ncerts - 1];
+ x509_ncas = 1;
+ }
- ret = gnutls_x509_trust_list_init(&list, 0);
- if (ret < 0)
- error (EXIT_FAILURE, 0, "gnutls_x509_trust_list_init: %s",
- gnutls_strerror (ret));
+ fprintf(stdout, "Loaded %d certificates, %d CAs and %d CRLs\n\n",
+ x509_ncerts, x509_ncas, x509_ncrls);
- ret = gnutls_x509_trust_list_add_cas(list, &x509_cert_list[x509_ncerts - 1], 1, 0);
+ ret = gnutls_x509_trust_list_add_cas(list, x509_ca_list, x509_ncas, 0);
if (ret < 0)
error (EXIT_FAILURE, 0, "gnutls_x509_trust_add_cas: %s",
gnutls_strerror (ret));
fprintf (outfile, ".\n\n");
- /* Verify using internal algorithm too. */
- {
- int verify_status;
-
- ret = gnutls_x509_crt_list_verify (x509_cert_list, x509_ncerts,
- &x509_cert_list[x509_ncerts - 1], 1,
- x509_crl_list,
- x509_ncrls,
- GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT |
- GNUTLS_VERIFY_DO_NOT_ALLOW_SAME,
- &verify_status);
- if (ret < 0)
- error (EXIT_FAILURE, 0, "gnutls_x509_crt_list_verify: %s",
- gnutls_strerror (ret));
-
- if (output != verify_status)
- {
- fprintf (outfile, "Chain verification output[via internal]: ");
- print_verification_res(outfile, verify_status);
- fprintf (outfile, ".\n");
- }
- }
-
gnutls_free(x509_cert_list);
gnutls_x509_trust_list_deinit(list, 1);
}
}
-void
+static void
verify_chain (void)
{
char *buf;
buf[size] = 0;
- _verify_x509_mem (buf, size);
+ _verify_x509_mem (buf, size, NULL, 0);
+
+}
+
+static void
+verify_certificate (common_info_st * cinfo)
+{
+ char *cert;
+ char *cas;
+ size_t cert_size, ca_size;
+ FILE * ca_file = fopen(cinfo->ca, "r");
+
+ if (ca_file == NULL)
+ error (EXIT_FAILURE, errno, "opening CA file");
+
+ cert = fread_file (infile, &cert_size);
+ if (cert == NULL)
+ error (EXIT_FAILURE, errno, "reading certificate chain");
+
+ cert[cert_size] = 0;
+
+ cas = fread_file (ca_file, &ca_size);
+ if (cas == NULL)
+ error (EXIT_FAILURE, errno, "reading CA list");
+
+ cas[ca_size] = 0;
+ fclose(ca_file);
+
+ _verify_x509_mem (cert, cert_size, cas, ca_size);
+
}