From: Nikos Mavrogiannopoulos Date: Wed, 2 Feb 2011 09:16:14 +0000 (+0100) Subject: Added new functionality to certtool, and can verify certificates against a list of... X-Git-Tag: gnutls_2_99_0~340 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b7b633ee1397f6572748d4a291a4c3a30cc7678f;p=thirdparty%2Fgnutls.git Added new functionality to certtool, and can verify certificates against a list of CAs using the --verify option. --- diff --git a/NEWS b/NEWS index f300148451..abda399d5d 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,10 @@ gnutls_x509_trust_list_*. ** certtool: Uses the new certificate verification functions for --verify-chain. +** certtool: Added new certificate verification functionality +using the --verify option. Combined with --load-ca-certificate +it can verify a certificate chain against a list of certificates. + ** libgnutls: The deprecated gnutls_x509_privkey_sign_hash() was replaced by gnutls_privkey_sign_hash2(). diff --git a/src/certtool-common.h b/src/certtool-common.h index b9b77d5600..bf08db2431 100644 --- a/src/certtool-common.h +++ b/src/certtool-common.h @@ -31,6 +31,7 @@ enum ACTION_REQUEST, ACTION_PUBKEY_INFO, ACTION_CERT_PUBKEY, + ACTION_VERIFY, }; #define TYPE_CRT 1 diff --git a/src/certtool-gaa.c b/src/certtool-gaa.c index 8ae957ace5..14a3876f3c 100644 --- a/src/certtool-gaa.c +++ b/src/certtool-gaa.c @@ -137,6 +137,7 @@ void gaa_help(void) __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."); @@ -196,53 +197,53 @@ typedef struct _gaainfo gaainfo; 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; @@ -302,7 +303,7 @@ static int gaa_error = 0; #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 @@ -348,14 +349,15 @@ static int gaa_error = 0; #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" @@ -708,6 +710,7 @@ static int gaa_get_option_num(char *str, int status) 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); @@ -765,6 +768,7 @@ static int gaa_get_option_num(char *str, int status) 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); @@ -822,14 +826,14 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) { 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; @@ -839,7 +843,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) 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; @@ -849,7 +853,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) 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; @@ -859,7 +863,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) 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; @@ -869,7 +873,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) 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; @@ -879,14 +883,14 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) 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; @@ -896,7 +900,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) 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; @@ -906,42 +910,42 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) 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; @@ -951,140 +955,140 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) 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; @@ -1094,7 +1098,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) 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; @@ -1104,7 +1108,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) 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; @@ -1114,7 +1118,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) 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; @@ -1124,7 +1128,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) 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; @@ -1134,7 +1138,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) 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; @@ -1144,7 +1148,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) 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; @@ -1154,30 +1158,37 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) 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: @@ -1260,7 +1271,7 @@ int gaa(int argc, char **argv, gaainfo *gaaval) 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; diff --git a/src/certtool-gaa.h b/src/certtool-gaa.h index 4e02a41dff..238d2331f1 100644 --- a/src/certtool-gaa.h +++ b/src/certtool-gaa.h @@ -8,53 +8,53 @@ typedef struct _gaainfo gaainfo; 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; diff --git a/src/certtool.c b/src/certtool.c index 842b3ef212..ebd1d8e9a6 100644 --- a/src/certtool.c +++ b/src/certtool.c @@ -58,7 +58,7 @@ void smime_to_pkcs7 (void); 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); @@ -72,6 +72,7 @@ void generate_self_signed (common_info_st *); 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); @@ -1112,6 +1113,9 @@ gaa_parser (int argc, char **argv) case ACTION_VERIFY_CHAIN: verify_chain (); break; + case ACTION_VERIFY: + verify_certificate (&cinfo); + break; case ACTION_PRIVKEY_INFO: privkey_info (); break; @@ -1998,19 +2002,44 @@ static int detailed_verification(gnutls_x509_crt_t cert, 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); @@ -2020,22 +2049,26 @@ _verify_x509_mem (const void *cert, int cert_size) 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)); @@ -2059,29 +2092,6 @@ _verify_x509_mem (const void *cert, int cert_size) 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); @@ -2148,7 +2158,7 @@ print_verification_res (FILE* outfile, unsigned int output) } } -void +static void verify_chain (void) { char *buf; @@ -2160,7 +2170,36 @@ verify_chain (void) 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); + } diff --git a/src/certtool.gaa b/src/certtool.gaa index e3e9f1c620..e979ba049f 100644 --- a/src/certtool.gaa +++ b/src/certtool.gaa @@ -31,6 +31,8 @@ option (q, generate-request) { $action=ACTION_GENERATE_REQUEST; } "Generate a PK option (e, verify-chain) { $action=ACTION_VERIFY_CHAIN; } "Verify a PEM encoded certificate chain. The last certificate in the chain must be a self signed one." +option (verify) { $action=ACTION_VERIFY; } "Verify a PEM encoded certificate chain. CA certificates must be loaded with --load-ca-certificate." + option (verify-crl) { $action=ACTION_VERIFY_CRL; } "Verify a CRL." option (generate-dh-params) { $action=ACTION_GENERATE_DH; } "Generate PKCS #3 encoded Diffie-Hellman parameters."