void Certificate::unpack(Blob::const_iterator& begin, Blob::const_iterator& end) { if (cert) { gnutls_x509_crt_deinit(cert); cert = nullptr; } gnutls_x509_crt_t* cert_list; unsigned cert_num; const gnutls_datum_t crt_dt {(uint8_t*)&(*begin), (unsigned)(end-begin)}; int err = gnutls_x509_crt_list_import2(&cert_list, &cert_num, &crt_dt, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED); if (err != GNUTLS_E_SUCCESS) err = gnutls_x509_crt_list_import2(&cert_list, &cert_num, &crt_dt, GNUTLS_X509_FMT_DER, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED); if (err != GNUTLS_E_SUCCESS || cert_num == 0) { cert = nullptr; throw CryptoException(std::string("Could not read certificate - ") + gnutls_strerror(err)); } cert = cert_list[0]; Certificate* crt = this; size_t i = 1; while (crt and i < cert_num) { crt->issuer = std::make_shared<Certificate>(cert_list[i++]); crt = crt->issuer.get(); } gnutls_free(cert_list); }
/** * gnutls_x509_trust_list_remove_trust_mem: * @list: The structure of the list * @cas: A buffer containing a list of CAs (optional) * @type: The format of the certificates * * This function will add the given certificate authorities * to the trusted list. * * Returns: The number of added elements is returned. * * Since: 3.1.10 **/ int gnutls_x509_trust_list_remove_trust_mem(gnutls_x509_trust_list_t list, const gnutls_datum_t * cas, gnutls_x509_crt_fmt_t type) { int ret; gnutls_x509_crt_t *x509_ca_list = NULL; unsigned int x509_ncas; unsigned int r = 0, i; if (cas != NULL && cas->data != NULL) { ret = gnutls_x509_crt_list_import2( &x509_ca_list, &x509_ncas, cas, type, 0); if (ret < 0) return gnutls_assert_val(ret); ret = gnutls_x509_trust_list_remove_cas(list, x509_ca_list, x509_ncas); for (i=0;i<x509_ncas;i++) gnutls_x509_crt_deinit(x509_ca_list[i]); gnutls_free(x509_ca_list); if (ret < 0) return gnutls_assert_val(ret); else r += ret; } return r; }
/** * gnutls_x509_trust_list_add_trust_mem: * @list: The list * @cas: A buffer containing a list of CAs (optional) * @crls: A buffer containing a list of CRLs (optional) * @type: The format of the certificates * @tl_flags: flags from %gnutls_trust_list_flags_t * @tl_vflags: gnutls_certificate_verify_flags if flags specifies GNUTLS_TL_VERIFY_CRL * * This function will add the given certificate authorities * to the trusted list. * * Returns: The number of added elements is returned. * * Since: 3.1 **/ int gnutls_x509_trust_list_add_trust_mem(gnutls_x509_trust_list_t list, const gnutls_datum_t * cas, const gnutls_datum_t * crls, gnutls_x509_crt_fmt_t type, unsigned int tl_flags, unsigned int tl_vflags) { int ret; gnutls_x509_crt_t *x509_ca_list = NULL; gnutls_x509_crl_t *x509_crl_list = NULL; unsigned int x509_ncas, x509_ncrls; unsigned int r = 0; if (cas != NULL && cas->data != NULL) { ret = gnutls_x509_crt_list_import2(&x509_ca_list, &x509_ncas, cas, type, 0); if (ret < 0) return gnutls_assert_val(ret); ret = gnutls_x509_trust_list_add_cas(list, x509_ca_list, x509_ncas, tl_flags); gnutls_free(x509_ca_list); if (ret < 0) return gnutls_assert_val(ret); else r += ret; } if (crls != NULL && crls->data != NULL) { ret = gnutls_x509_crl_list_import2(&x509_crl_list, &x509_ncrls, crls, type, 0); if (ret < 0) return gnutls_assert_val(ret); ret = gnutls_x509_trust_list_add_crls(list, x509_crl_list, x509_ncrls, tl_flags|GNUTLS_TL_NO_DUPLICATES, tl_vflags); gnutls_free(x509_crl_list); if (ret < 0) return gnutls_assert_val(ret); else r += ret; } return r; }
/* Loads a certificate list */ gnutls_x509_crt_t *load_cert_list(int mand, size_t * crt_size, common_info_st * info) { FILE *fd; static gnutls_x509_crt_t *crt; int ret; gnutls_datum_t dat; unsigned size; unsigned int crt_max; *crt_size = 0; if (info->verbose) fprintf(stderr, "Loading certificate list...\n"); if (info->cert == NULL) { if (mand) { fprintf(stderr, "missing --load-certificate\n"); exit(1); } else return NULL; } fd = fopen(info->cert, "r"); if (fd == NULL) { fprintf(stderr, "Could not open %s\n", info->cert); exit(1); } fix_lbuffer(file_size(fd)); size = fread(lbuffer, 1, lbuffer_size - 1, fd); lbuffer[size] = 0; fclose(fd); dat.data = (void *) lbuffer; dat.size = size; ret = gnutls_x509_crt_list_import2(&crt, &crt_max, &dat, GNUTLS_X509_FMT_PEM, 0); if (ret < 0) { fprintf(stderr, "Error loading certificates: %s\n", gnutls_strerror(ret)); exit(1); } *crt_size = crt_max; if (info->verbose) fprintf(stderr, "Loaded %d certificates.\n", (int) crt_max); return crt; }
static int import_key(gnutls_certificate_credentials_t xcred, const gnutls_datum_t *skey, const gnutls_datum_t *cert) { gnutls_x509_privkey_t key; gnutls_x509_crt_t *crt_list; unsigned crt_list_size, idx, i; gnutls_datum_t tcert; int ret; assert(gnutls_x509_privkey_init(&key)>=0); ret = gnutls_x509_crt_list_import2(&crt_list, &crt_list_size, cert, GNUTLS_X509_FMT_PEM, 0); if (ret < 0) { fail("error in gnutls_x509_crt_list_import2: %s\n", gnutls_strerror(ret)); } ret = gnutls_x509_privkey_import(key, skey, GNUTLS_X509_FMT_PEM); if (ret < 0) { fail("error in key import: %s\n", gnutls_strerror(ret)); } ret = gnutls_certificate_set_x509_key(xcred, crt_list, crt_list_size, key); if (ret < 0) { success("error in gnutls_certificate_set_x509_key: %s\n", gnutls_strerror(ret)); idx = ret; goto cleanup; } /* return index */ idx = ret; /* verify whether the stored certificate match the ones we have */ for (i=0;i<MIN(2, crt_list_size);i++) { ret = gnutls_certificate_get_crt_raw(xcred, idx, i, &tcert); if (ret < 0) { fail("error in %d: cert: %d: %s\n", __LINE__, i, gnutls_strerror(ret)); exit(1); } compare(&tcert, cert->data+i); } cleanup: gnutls_x509_privkey_deinit(key); for (i=0;i<crt_list_size;i++) { gnutls_x509_crt_deinit(crt_list[i]); } gnutls_free(crt_list); return idx; }
static void test_success2(const char *name, const char *prio) { int ret; /* Server stuff. */ gnutls_certificate_credentials_t serverx509cred; gnutls_session_t server; int sret = GNUTLS_E_AGAIN; /* Client stuff. */ gnutls_certificate_credentials_t clientx509cred; gnutls_session_t client; int cret = GNUTLS_E_AGAIN; gnutls_x509_crt_t *crts; unsigned int crts_size; unsigned i; gnutls_x509_privkey_t pkey; unsigned status; success("testing cert verification success2 for %s\n", name); to_server_len = 0; to_client_len = 0; ret = gnutls_x509_crt_list_import2(&crts, &crts_size, &server_cert, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_privkey_init(&pkey); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_privkey_import(pkey, &server_key, GNUTLS_X509_FMT_PEM); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } /* Init server */ gnutls_certificate_allocate_credentials(&serverx509cred); gnutls_certificate_set_x509_key(serverx509cred, crts, crts_size, pkey); gnutls_x509_privkey_deinit(pkey); for (i=0;i<crts_size;i++) gnutls_x509_crt_deinit(crts[i]); gnutls_free(crts); gnutls_init(&server, GNUTLS_SERVER); gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, serverx509cred); assert(gnutls_priority_set_direct(server, prio, NULL)>=0); gnutls_transport_set_push_function(server, server_push); gnutls_transport_set_pull_function(server, server_pull); gnutls_transport_set_ptr(server, server); gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUEST); /* Init client */ /* Init client */ ret = gnutls_certificate_allocate_credentials(&clientx509cred); if (ret < 0) exit(1); ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) exit(1); ret = gnutls_certificate_set_x509_key_mem(clientx509cred, &cli_cert, &cli_key, GNUTLS_X509_FMT_PEM); ret = gnutls_init(&client, GNUTLS_CLIENT); if (ret < 0) exit(1); ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, clientx509cred); if (ret < 0) exit(1); assert(gnutls_priority_set_direct(client, prio, NULL)>=0); gnutls_transport_set_push_function(client, client_push); gnutls_transport_set_pull_function(client, client_pull); gnutls_transport_set_ptr(client, client); gnutls_session_set_verify_cert(client, "localhost", 0); HANDSHAKE(client, server); status = gnutls_session_get_verify_cert_status(client); if (status != 0) { fail("%s: should have accepted: %u!\n", __func__, status); exit(1); } gnutls_deinit(client); gnutls_deinit(server); gnutls_certificate_free_credentials(serverx509cred); gnutls_certificate_free_credentials(clientx509cred); }
static void test_failure(const char *name, const char *prio) { int ret; /* Server stuff. */ gnutls_certificate_credentials_t serverx509cred; gnutls_session_t server; int sret = GNUTLS_E_AGAIN; /* Client stuff. */ gnutls_certificate_credentials_t clientx509cred; gnutls_session_t client; int cret = GNUTLS_E_AGAIN; gnutls_x509_crt_t *crts; unsigned int crts_size; unsigned i; gnutls_typed_vdata_st vdata[2]; gnutls_x509_privkey_t pkey; unsigned status; success("testing cert verification failure for %s\n", name); to_server_len = 0; to_client_len = 0; ret = gnutls_x509_crt_list_import2(&crts, &crts_size, &server_cert, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_privkey_init(&pkey); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_privkey_import(pkey, &server_key, GNUTLS_X509_FMT_PEM); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } /* Init server */ gnutls_certificate_allocate_credentials(&serverx509cred); gnutls_certificate_set_x509_key(serverx509cred, crts, crts_size, pkey); gnutls_x509_privkey_deinit(pkey); for (i=0;i<crts_size;i++) gnutls_x509_crt_deinit(crts[i]); gnutls_free(crts); gnutls_init(&server, GNUTLS_SERVER); gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, serverx509cred); assert(gnutls_priority_set_direct(server, prio, NULL) >= 0); gnutls_transport_set_push_function(server, server_push); gnutls_transport_set_pull_function(server, server_pull); gnutls_transport_set_ptr(server, server); gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUEST); /* Init client */ /* Init client */ ret = gnutls_certificate_allocate_credentials(&clientx509cred); if (ret < 0) exit(1); ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) exit(1); ret = gnutls_certificate_set_x509_key_mem(clientx509cred, &cli_cert, &cli_key, GNUTLS_X509_FMT_PEM); ret = gnutls_init(&client, GNUTLS_CLIENT); if (ret < 0) exit(1); ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, clientx509cred); if (ret < 0) exit(1); assert(gnutls_priority_set_direct(client, prio, NULL) >= 0); gnutls_transport_set_push_function(client, client_push); gnutls_transport_set_pull_function(client, client_pull); gnutls_transport_set_ptr(client, client); memset(vdata, 0, sizeof(vdata)); /* check with wrong hostname */ vdata[0].type = GNUTLS_DT_DNS_HOSTNAME; vdata[0].data = (void*)"localhost1"; vdata[1].type = GNUTLS_DT_KEY_PURPOSE_OID; vdata[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER; gnutls_session_set_verify_cert2(client, vdata, 2, 0); HANDSHAKE_EXPECT(client, server, GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR, GNUTLS_E_AGAIN); status = gnutls_session_get_verify_cert_status(client); if (status == 0) { fail("should not have accepted!\n"); exit(1); } gnutls_deinit(client); gnutls_deinit(server); gnutls_certificate_free_credentials(serverx509cred); gnutls_certificate_free_credentials(clientx509cred); }
static void dane_check(const char *host, const char *proto, unsigned int port, common_info_st * cinfo) { #ifdef HAVE_DANE dane_state_t s; dane_query_t q; int ret, retcode = 1; unsigned entries; unsigned int flags = DANE_F_IGNORE_LOCAL_RESOLVER, i; unsigned int usage, type, match; gnutls_datum_t data, file; size_t size; unsigned del = 0; unsigned vflags = DANE_VFLAG_FAIL_IF_NOT_CHECKED; const char *cstr; char *str; gnutls_x509_crt_t *clist = NULL; unsigned int clist_size = 0; gnutls_datum_t certs[MAX_CLIST_SIZE]; if (ENABLED_OPT(LOCAL_DNS)) flags = 0; if (HAVE_OPT(INSECURE)) flags |= DANE_F_INSECURE; if (HAVE_OPT(CHECK_EE)) vflags |= DANE_VFLAG_ONLY_CHECK_EE_USAGE; if (HAVE_OPT(CHECK_CA)) vflags |= DANE_VFLAG_ONLY_CHECK_CA_USAGE; if (!cinfo->cert) { const char *app_proto = NULL; if (HAVE_OPT(APP_PROTO)) app_proto = OPT_ARG(APP_PROTO); cinfo->cert = obtain_cert(host, proto, port, app_proto, HAVE_OPT(QUIET)); del = 1; } if (!HAVE_OPT(QUIET)) fprintf(stderr, "Querying DNS for %s (%s:%d)...\n", host, proto, port); ret = dane_state_init(&s, flags); if (ret < 0) { fprintf(stderr, "dane_state_init: %s\n", dane_strerror(ret)); retcode = 1; goto error; } if (HAVE_OPT(DLV)) { ret = dane_state_set_dlv_file(s, OPT_ARG(DLV)); if (ret < 0) { fprintf(stderr, "dane_state_set_dlv_file: %s\n", dane_strerror(ret)); retcode = 1; goto error; } } ret = dane_query_tlsa(s, &q, host, proto, port); if (ret < 0) { fprintf(stderr, "dane_query_tlsa: %s\n", dane_strerror(ret)); retcode = 1; goto error; } if (ENABLED_OPT(PRINT_RAW)) { gnutls_datum_t t; char **dane_data; int *dane_data_len; int secure; int bogus; ret = dane_query_to_raw_tlsa(q, &entries, &dane_data, &dane_data_len, &secure, &bogus); if (ret < 0) { fprintf(stderr, "dane_query_to_raw_tlsa: %s\n", dane_strerror(ret)); retcode = 1; goto error; } for (i=0;i<entries;i++) { size_t str_size; t.data = (void*)dane_data[i]; t.size = dane_data_len[i]; str_size = t.size * 2 + 1; str = gnutls_malloc(str_size); ret = gnutls_hex_encode(&t, str, &str_size); if (ret < 0) { fprintf(stderr, "gnutls_hex_encode: %s\n", dane_strerror(ret)); retcode = 1; goto error; } fprintf(outfile, "[%u]: %s\n", i, str); gnutls_free(str); } fprintf(outfile, "\n"); } if (cinfo->cert) { ret = gnutls_load_file(cinfo->cert, &file); if (ret < 0) { fprintf(stderr, "gnutls_load_file: %s\n", gnutls_strerror(ret)); retcode = 1; goto error; } ret = gnutls_x509_crt_list_import2(&clist, &clist_size, &file, cinfo-> incert_format, 0); if (ret < 0) { fprintf(stderr, "gnutls_x509_crt_list_import2: %s\n", gnutls_strerror(ret)); retcode = 1; goto error; } if (clist_size > 0) { for (i = 0; i < MIN(MAX_CLIST_SIZE,clist_size); i++) { ret = gnutls_x509_crt_export2(clist [i], GNUTLS_X509_FMT_DER, &certs [i]); if (ret < 0) { fprintf(stderr, "gnutls_x509_crt_export2: %s\n", gnutls_strerror (ret)); retcode = 1; goto error; } } } } entries = dane_query_entries(q); for (i = 0; i < entries; i++) { ret = dane_query_data(q, i, &usage, &type, &match, &data); if (ret < 0) { fprintf(stderr, "dane_query_data: %s\n", dane_strerror(ret)); retcode = 1; goto error; } size = lbuffer_size; ret = gnutls_hex_encode(&data, (void *) lbuffer, &size); if (ret < 0) { fprintf(stderr, "gnutls_hex_encode: %s\n", dane_strerror(ret)); retcode = 1; goto error; } if (entries > 1 && !HAVE_OPT(QUIET)) fprintf(outfile, "\n==== Entry %d ====\n", i + 1); fprintf(outfile, "_%u._%s.%s. IN TLSA ( %.2x %.2x %.2x %s )\n", port, proto, host, usage, type, match, lbuffer); if (!HAVE_OPT(QUIET)) { cstr = dane_cert_usage_name(usage); if (cstr == NULL) cstr= "Unknown"; fprintf(outfile, "Certificate usage: %s (%.2x)\n", cstr, usage); cstr = dane_cert_type_name(type); if (cstr == NULL) cstr= "Unknown"; fprintf(outfile, "Certificate type: %s (%.2x)\n", cstr, type); cstr = dane_match_type_name(match); if (cstr == NULL) cstr= "Unknown"; fprintf(outfile, "Contents: %s (%.2x)\n", cstr, match); fprintf(outfile, "Data: %s\n", lbuffer); } /* Verify the DANE data */ if (cinfo->cert) { unsigned int status; gnutls_datum_t out; ret = dane_verify_crt(s, certs, clist_size, GNUTLS_CRT_X509, host, proto, port, 0, vflags, &status); if (ret < 0) { fprintf(stderr, "dane_verify_crt: %s\n", dane_strerror(ret)); retcode = 1; goto error; } ret = dane_verification_status_print(status, &out, 0); if (ret < 0) { fprintf(stderr, "dane_verification_status_print: %s\n", dane_strerror(ret)); retcode = 1; goto error; } if (!HAVE_OPT(QUIET)) fprintf(outfile, "\nVerification: %s\n", out.data); gnutls_free(out.data); /* if there is at least one correct accept */ if (status == 0) retcode = 0; } else { fprintf(stderr, "\nCertificate could not be obtained. You can explicitly load the certificate using --load-certificate.\n"); } } if (clist_size > 0) { for (i = 0; i < clist_size; i++) { gnutls_free(certs[i].data); gnutls_x509_crt_deinit(clist[i]); } gnutls_free(clist); } dane_query_deinit(q); dane_state_deinit(s); error: if (del != 0 && cinfo->cert) { remove(cinfo->cert); } exit(retcode); #else fprintf(stderr, "This functionality is disabled (GnuTLS was not compiled with support for DANE).\n"); return; #endif }
static int server_cert_callback(gnutls_session_t session, const struct gnutls_cert_retr_st *info, gnutls_pcert_st **pcert, unsigned int *pcert_length, gnutls_ocsp_data_st **ocsp, unsigned int *ocsp_length, gnutls_privkey_t *pkey, unsigned int *flags) { int ret; gnutls_pcert_st *p; gnutls_privkey_t lkey; gnutls_x509_crt_t *certs; unsigned certs_size, i; if (server_pkey == NULL) { p = gnutls_malloc(2 * sizeof(*p)); if (p == NULL) return -1; ocspdata[0].response.data = (void*)OCSP_DATA; ocspdata[0].response.size = OCSP_SIZE; ocspdata[0].exptime = 0; ocspdata[1].response.data = (void*)OCSP_DATA; ocspdata[1].response.size = OCSP_SIZE; ocspdata[1].exptime = 0; ret = gnutls_x509_crt_list_import2(&certs, &certs_size, &server_ca3_localhost_cert_chain, GNUTLS_X509_FMT_PEM, 0); if (ret < 0) return -1; ret = gnutls_pcert_import_x509_list(p, certs, &certs_size, 0); if (ret < 0) return -1; for (i = 0; i < certs_size; i++) gnutls_x509_crt_deinit(certs[i]); gnutls_free(certs); ret = gnutls_privkey_init(&lkey); if (ret < 0) return -1; ret = gnutls_privkey_import_x509_raw(lkey, &server_ca3_key, GNUTLS_X509_FMT_PEM, NULL, 0); if (ret < 0) return -1; server_pcert = p; server_pkey = lkey; *pcert = p; *pcert_length = 2; *pkey = lkey; *ocsp = ocspdata; *ocsp_length = 2; } else { *pcert = server_pcert; *pcert_length = 2; *pkey = server_pkey; *ocsp = ocspdata; *ocsp_length = 2; } return 0; }
void doit(void) { int exit_code = EXIT_SUCCESS; int ret; /* Server stuff. */ gnutls_certificate_credentials_t serverx509cred; gnutls_session_t server; int sret = GNUTLS_E_AGAIN; /* Client stuff. */ gnutls_certificate_credentials_t clientx509cred; gnutls_session_t client; int cret = GNUTLS_E_AGAIN; gnutls_x509_crt_t *crts; unsigned int crts_size; unsigned i; gnutls_x509_privkey_t pkey; /* General init. */ global_init(); gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(2); ret = gnutls_x509_crt_list_import2(&crts, &crts_size, &server_cert, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_privkey_init(&pkey); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_privkey_import(pkey, &server_key, GNUTLS_X509_FMT_PEM); if (ret < 0) { fprintf(stderr, "error: %s\n", gnutls_strerror(ret)); exit(1); } /* Init server */ gnutls_certificate_allocate_credentials(&serverx509cred); gnutls_certificate_set_x509_key(serverx509cred, crts, crts_size, pkey); gnutls_x509_privkey_deinit(pkey); for (i=0;i<crts_size;i++) gnutls_x509_crt_deinit(crts[i]); gnutls_free(crts); gnutls_init(&server, GNUTLS_SERVER); gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, serverx509cred); gnutls_priority_set_direct(server, "NORMAL:-CIPHER-ALL:+AES-128-GCM", NULL); gnutls_transport_set_push_function(server, server_push); gnutls_transport_set_pull_function(server, server_pull); gnutls_transport_set_ptr(server, server); gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUEST); /* Init client */ /* Init client */ ret = gnutls_certificate_allocate_credentials(&clientx509cred); if (ret < 0) exit(1); ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) exit(1); gnutls_certificate_set_retrieve_function2(clientx509cred, cert_callback); ret = gnutls_init(&client, GNUTLS_CLIENT); if (ret < 0) exit(1); ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, clientx509cred); if (ret < 0) exit(1); gnutls_priority_set_direct(client, "NORMAL", NULL); gnutls_transport_set_push_function(client, client_push); gnutls_transport_set_pull_function(client, client_pull); gnutls_transport_set_ptr(client, client); HANDSHAKE(client, server); if (gnutls_certificate_get_ours(client) == NULL) { fail("client certificate was not sent!\n"); exit(1); } /* check gnutls_certificate_get_ours() - server side */ { const gnutls_datum_t *mcert; gnutls_datum_t scert; gnutls_x509_crt_t crt; mcert = gnutls_certificate_get_ours(server); if (mcert == NULL) { fail("gnutls_certificate_get_ours(): failed\n"); exit(1); } gnutls_x509_crt_init(&crt); ret = gnutls_x509_crt_import(crt, &server_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) { fail("gnutls_x509_crt_import: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &scert); if (ret < 0) { fail("gnutls_x509_crt_export2: %s\n", gnutls_strerror(ret)); exit(1); } gnutls_x509_crt_deinit(crt); if (scert.size != mcert->size || memcmp(scert.data, mcert->data, mcert->size) != 0) { fail("gnutls_certificate_get_ours output doesn't match cert\n"); exit(1); } gnutls_free(scert.data); } /* check gnutls_certificate_get_ours() - client side */ { const gnutls_datum_t *mcert; gnutls_datum_t ccert; gnutls_x509_crt_t crt; mcert = gnutls_certificate_get_ours(client); if (mcert == NULL) { fail("gnutls_certificate_get_ours(): failed\n"); exit(1); } gnutls_x509_crt_init(&crt); ret = gnutls_x509_crt_import(crt, &cli_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) { fail("gnutls_x509_crt_import: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &ccert); if (ret < 0) { fail("gnutls_x509_crt_export2: %s\n", gnutls_strerror(ret)); exit(1); } gnutls_x509_crt_deinit(crt); if (ccert.size != mcert->size || memcmp(ccert.data, mcert->data, mcert->size) != 0) { fail("gnutls_certificate_get_ours output doesn't match cert\n"); exit(1); } gnutls_free(ccert.data); } /* check the number of certificates received */ { unsigned cert_list_size = 0; gnutls_typed_vdata_st data[2]; unsigned status; memset(data, 0, sizeof(data)); /* check with wrong hostname */ data[0].type = GNUTLS_DT_DNS_HOSTNAME; data[0].data = (void*)"localhost1"; data[1].type = GNUTLS_DT_KEY_PURPOSE_OID; data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER; gnutls_certificate_get_peers(client, &cert_list_size); if (cert_list_size < 2) { fprintf(stderr, "received a certificate list of %d!\n", cert_list_size); exit(1); } ret = gnutls_certificate_verify_peers(client, data, 2, &status); if (ret < 0) { fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret)); exit(1); } if (status == 0) { fprintf(stderr, "should not have accepted!\n"); exit(1); } /* check with wrong purpose */ data[0].type = GNUTLS_DT_DNS_HOSTNAME; data[0].data = (void*)"localhost"; data[1].type = GNUTLS_DT_KEY_PURPOSE_OID; data[1].data = (void*)GNUTLS_KP_TLS_WWW_CLIENT; gnutls_certificate_get_peers(client, &cert_list_size); if (cert_list_size < 2) { fprintf(stderr, "received a certificate list of %d!\n", cert_list_size); exit(1); } ret = gnutls_certificate_verify_peers(client, data, 2, &status); if (ret < 0) { fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret)); exit(1); } if (status == 0) { fprintf(stderr, "should not have accepted!\n"); exit(1); } /* check with correct purpose */ data[0].type = GNUTLS_DT_DNS_HOSTNAME; data[0].data = (void*)"localhost"; data[1].type = GNUTLS_DT_KEY_PURPOSE_OID; data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER; ret = gnutls_certificate_verify_peers(client, data, 2, &status); if (ret < 0) { fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret)); exit(1); } if (status != 0) { fprintf(stderr, "could not verify certificate: %.4x\n", status); exit(1); } } if (gnutls_certificate_client_get_request_status(client) == 0) { fail("gnutls_certificate_client_get_request_status - 2 failed\n"); exit(1); } gnutls_bye(client, GNUTLS_SHUT_RDWR); gnutls_bye(server, GNUTLS_SHUT_RDWR); gnutls_deinit(client); gnutls_deinit(server); gnutls_certificate_free_credentials(serverx509cred); gnutls_certificate_free_credentials(clientx509cred); gnutls_global_deinit(); if (debug > 0) { if (exit_code == 0) puts("Self-test successful"); else puts("Self-test failed"); } }
static int _verify_response(gnutls_datum_t * data, gnutls_datum_t * nonce, gnutls_x509_crt_t signer) { gnutls_ocsp_resp_t resp; int ret; size_t size; gnutls_x509_crt_t *x509_ca_list = NULL; gnutls_x509_trust_list_t list; unsigned int x509_ncas = 0; unsigned verify; gnutls_datum_t dat; ret = gnutls_ocsp_resp_init(&resp); if (ret < 0) { fprintf(stderr, "ocsp_resp_init: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_ocsp_resp_import(resp, data); if (ret < 0) { fprintf(stderr, "importing response: %s\n", gnutls_strerror(ret)); exit(1); } if (nonce) { gnutls_datum_t rnonce; ret = gnutls_ocsp_resp_get_nonce(resp, NULL, &rnonce); if (ret < 0) { fprintf(stderr, "could not read response's nonce: %s\n", gnutls_strerror(ret)); exit(1); } if (rnonce.size != nonce->size || memcmp(nonce->data, rnonce.data, nonce->size) != 0) { fprintf(stderr, "nonce in the response doesn't match\n"); exit(1); } gnutls_free(rnonce.data); } if (HAVE_OPT(LOAD_TRUST)) { dat.data = (void *) read_binary_file(OPT_ARG(LOAD_TRUST), &size); if (dat.data == NULL) { fprintf(stderr, "reading --load-trust: %s\n", OPT_ARG(LOAD_TRUST)); exit(1); } dat.size = size; ret = gnutls_x509_trust_list_init(&list, 0); if (ret < 0) { fprintf(stderr, "gnutls_x509_trust_list_init: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_crt_list_import2(&x509_ca_list, &x509_ncas, &dat, GNUTLS_X509_FMT_PEM, 0); if (ret < 0 || x509_ncas < 1) { fprintf(stderr, "error parsing CAs: %s\n", gnutls_strerror(ret)); exit(1); } if (HAVE_OPT(VERBOSE)) { unsigned int i; printf("Trust anchors:\n"); for (i = 0; i < x509_ncas; i++) { gnutls_datum_t out; ret = gnutls_x509_crt_print(x509_ca_list[i], GNUTLS_CRT_PRINT_ONELINE, &out); if (ret < 0) { fprintf(stderr, "gnutls_x509_crt_print: %s\n", gnutls_strerror(ret)); exit(1); } printf("%d: %.*s\n", i, out.size, out.data); gnutls_free(out.data); } printf("\n"); } ret = gnutls_x509_trust_list_add_cas(list, x509_ca_list, x509_ncas, 0); if (ret < 0) { fprintf(stderr, "gnutls_x509_trust_add_cas: %s\n", gnutls_strerror(ret)); exit(1); } if (HAVE_OPT(VERBOSE)) fprintf(stdout, "Loaded %d trust anchors\n", x509_ncas); ret = gnutls_ocsp_resp_verify(resp, list, &verify, 0); if (ret < 0) { fprintf(stderr, "gnutls_ocsp_resp_verify: %s\n", gnutls_strerror(ret)); exit(1); } } else if (signer) { if (HAVE_OPT(VERBOSE)) { gnutls_datum_t out; ret = gnutls_x509_crt_print(signer, GNUTLS_CRT_PRINT_ONELINE, &out); if (ret < 0) { fprintf(stderr, "gnutls_x509_crt_print: %s\n", gnutls_strerror(ret)); exit(1); } printf("Signer: %.*s\n", out.size, out.data); gnutls_free(out.data); printf("\n"); } ret = gnutls_ocsp_resp_verify_direct(resp, signer, &verify, 0); if (ret < 0) { fprintf(stderr, "gnutls_ocsp_resp_verify_direct: %s\n", gnutls_strerror(ret)); exit(1); } } else { fprintf(stderr, "missing --load-trust or --load-signer\n"); exit(1); } printf("Verifying OCSP Response: "); print_ocsp_verify_res(verify); printf(".\n"); gnutls_ocsp_resp_deinit(resp); return verify; }
void doit(void) { int ret; gnutls_datum_t data; gnutls_x509_crt_t *crts; unsigned int crts_size, i; gnutls_x509_trust_list_t tl; unsigned int status, flags = GNUTLS_VERIFY_ALLOW_UNSORTED_CHAIN; unsigned int not_flags = GNUTLS_VERIFY_DO_NOT_ALLOW_UNSORTED_CHAIN; /* this must be called once in the program */ global_init(); gnutls_global_set_time_function(mytime); gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(6); /* test for gnutls_certificate_get_issuer() */ gnutls_x509_trust_list_init(&tl, 0); ret = gnutls_x509_trust_list_add_trust_mem(tl, &ca, NULL, GNUTLS_X509_FMT_PEM, 0, 0); if (ret < 0) { fail("gnutls_x509_trust_list_add_trust_mem\n"); exit(1); } /* Chain 1 */ data.data = (void *) chain1; data.size = sizeof(chain1); ret = gnutls_x509_crt_list_import2(&crts, &crts_size, &data, GNUTLS_X509_FMT_PEM, 0); if (ret < 0) { fail("gnutls_x509_crt_list_import2: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_trust_list_verify_crt(tl, crts, crts_size, flags, &status, NULL); if (ret < 0 || status != 0) { fail("gnutls_x509_trust_list_verify_crt - 1\n"); exit(1); } for (i = 0; i < crts_size; i++) gnutls_x509_crt_deinit(crts[i]); gnutls_free(crts); /* Chain 2 */ data.data = (void *) chain2; data.size = sizeof(chain2); /* verify whether the GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED flag is * considered by gnutls_x509_crt_list_import2() */ ret = gnutls_x509_crt_list_import2(&crts, &crts_size, &data, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED); if (ret != GNUTLS_E_CERTIFICATE_LIST_UNSORTED) { fail("gnutls_x509_crt_list_import2 with flag GNUTLS_E_CERTIFICATE_LIST_UNSORTED on unsorted chain didn't fail: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_crt_list_import2(&crts, &crts_size, &data, GNUTLS_X509_FMT_PEM, 0); if (ret < 0) { fail("gnutls_x509_crt_list_import2: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_trust_list_verify_crt(tl, crts, crts_size, flags, &status, NULL); if (ret < 0 || status != 0) { fail("gnutls_x509_trust_list_verify_crt - 2\n"); exit(1); } for (i = 0; i < crts_size; i++) gnutls_x509_crt_deinit(crts[i]); gnutls_free(crts); /* Chain 3 */ data.data = (void *) chain3; data.size = sizeof(chain3); ret = gnutls_x509_crt_list_import2(&crts, &crts_size, &data, GNUTLS_X509_FMT_PEM, 0); if (ret < 0) { fail("gnutls_x509_crt_list_import2: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_trust_list_verify_crt(tl, crts, crts_size, flags, &status, NULL); if (ret < 0 || status != 0) { fail("gnutls_x509_trust_list_verify_crt - 3\n"); exit(1); } for (i = 0; i < crts_size; i++) gnutls_x509_crt_deinit(crts[i]); gnutls_free(crts); /* Chain 4 */ data.data = (void *) chain4; data.size = sizeof(chain4); ret = gnutls_x509_crt_list_import2(&crts, &crts_size, &data, GNUTLS_X509_FMT_PEM, 0); if (ret < 0) { fail("gnutls_x509_crt_list_import2: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_trust_list_verify_crt(tl, crts, crts_size, flags, &status, NULL); if (ret < 0 || status != 0) { fail("gnutls_x509_trust_list_verify_crt - 4\n"); exit(1); } for (i = 0; i < crts_size; i++) gnutls_x509_crt_deinit(crts[i]); gnutls_free(crts); /* Check if an unsorted list would fail if the unsorted flag is not given */ data.data = (void *) chain2; data.size = sizeof(chain2); ret = gnutls_x509_crt_list_import2(&crts, &crts_size, &data, GNUTLS_X509_FMT_PEM, 0); if (ret < 0) { fail("gnutls_x509_crt_list_import2: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_trust_list_verify_crt(tl, crts, crts_size, not_flags, &status, NULL); if (ret < 0 || status == 0) { fail("gnutls_x509_trust_list_verify_crt - 5\n"); exit(1); } for (i = 0; i < crts_size; i++) gnutls_x509_crt_deinit(crts[i]); gnutls_free(crts); gnutls_x509_trust_list_deinit(tl, 1); gnutls_global_deinit(); if (debug) success("success"); }
static int _verify_response (gnutls_datum_t *data) { gnutls_ocsp_resp_t resp; int ret; size_t size; gnutls_x509_crt_t *x509_ca_list = NULL; unsigned int x509_ncas = 0; gnutls_x509_trust_list_t list; gnutls_x509_crt_t signer; unsigned verify; gnutls_datum_t dat; ret = gnutls_ocsp_resp_init (&resp); if (ret < 0) error (EXIT_FAILURE, 0, "ocsp_resp_init: %s", gnutls_strerror (ret)); ret = gnutls_ocsp_resp_import (resp, data); if (ret < 0) error (EXIT_FAILURE, 0, "importing response: %s", gnutls_strerror (ret)); if (HAVE_OPT(LOAD_TRUST)) { dat.data = (void*)read_binary_file (OPT_ARG(LOAD_TRUST), &size); if (dat.data == NULL) error (EXIT_FAILURE, errno, "reading --load-trust: %s", OPT_ARG(LOAD_TRUST)); dat.size = 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)); ret = gnutls_x509_crt_list_import2 (&x509_ca_list, &x509_ncas, &dat, GNUTLS_X509_FMT_PEM, 0); if (ret < 0 || x509_ncas < 1) error (EXIT_FAILURE, 0, "error parsing CAs: %s", gnutls_strerror (ret)); if (HAVE_OPT(VERBOSE)) { unsigned int i; printf ("Trust anchors:\n"); for (i = 0; i < x509_ncas; i++) { gnutls_datum_t out; ret = gnutls_x509_crt_print (x509_ca_list[i], GNUTLS_CRT_PRINT_ONELINE, &out); if (ret < 0) error (EXIT_FAILURE, 0, "gnutls_x509_crt_print: %s", gnutls_strerror (ret)); printf ("%d: %.*s\n", i, out.size, out.data); gnutls_free (out.data); } printf("\n"); } 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)); if (HAVE_OPT(VERBOSE)) fprintf (stdout, "Loaded %d trust anchors\n", x509_ncas); ret = gnutls_ocsp_resp_verify (resp, list, &verify, 0); if (ret < 0) error (EXIT_FAILURE, 0, "gnutls_ocsp_resp_verify: %s", gnutls_strerror (ret)); } else if (HAVE_OPT(LOAD_SIGNER)) { ret = gnutls_x509_crt_init (&signer); if (ret < 0) error (EXIT_FAILURE, 0, "crt_init: %s", gnutls_strerror (ret)); dat.data = (void*)read_binary_file (OPT_ARG(LOAD_SIGNER), &size); if (dat.data == NULL) error (EXIT_FAILURE, errno, "reading --load-signer: %s", OPT_ARG(LOAD_SIGNER)); dat.size = size; ret = gnutls_x509_crt_import (signer, &dat, encoding); free (dat.data); if (ret < 0) error (EXIT_FAILURE, 0, "importing --load-signer: %s: %s", OPT_ARG(LOAD_SIGNER), gnutls_strerror (ret)); if (HAVE_OPT(VERBOSE)) { gnutls_datum_t out; ret = gnutls_x509_crt_print (signer, GNUTLS_CRT_PRINT_ONELINE, &out); if (ret < 0) error (EXIT_FAILURE, 0, "gnutls_x509_crt_print: %s", gnutls_strerror (ret)); printf ("Signer: %.*s\n", out.size, out.data); gnutls_free (out.data); printf("\n"); } ret = gnutls_ocsp_resp_verify_direct (resp, signer, &verify, 0); if (ret < 0) error (EXIT_FAILURE, 0, "gnutls_ocsp_resp_verify_direct: %s", gnutls_strerror (ret)); } else error (EXIT_FAILURE, 0, "missing --load-trust or --load-signer"); printf ("Verifying OCSP Response: "); print_ocsp_verify_res (verify); printf (".\n"); gnutls_ocsp_resp_deinit (resp); return verify; }
static void dane_check(const char *host, const char *proto, unsigned int port, common_info_st * cinfo) { #ifdef HAVE_DANE dane_state_t s; dane_query_t q; int ret, retcode = 0; unsigned entries; unsigned int flags = DANE_F_IGNORE_LOCAL_RESOLVER, i; unsigned int usage, type, match; gnutls_datum_t data, file; size_t size; unsigned vflags = DANE_VFLAG_FAIL_IF_NOT_CHECKED; if (ENABLED_OPT(LOCAL_DNS)) flags = 0; if (HAVE_OPT(INSECURE)) flags |= DANE_F_INSECURE; if (HAVE_OPT(CHECK_EE)) vflags |= DANE_VFLAG_ONLY_CHECK_EE_USAGE; if (HAVE_OPT(CHECK_CA)) vflags |= DANE_VFLAG_ONLY_CHECK_CA_USAGE; printf("Querying %s (%s:%d)...\n", host, proto, port); ret = dane_state_init(&s, flags); if (ret < 0) { fprintf(stderr, "dane_state_init: %s\n", dane_strerror(ret)); exit(1); } if (HAVE_OPT(DLV)) { ret = dane_state_set_dlv_file(s, OPT_ARG(DLV)); if (ret < 0) { fprintf(stderr, "dane_state_set_dlv_file: %s\n", dane_strerror(ret)); exit(1); } } ret = dane_query_tlsa(s, &q, host, proto, port); if (ret < 0) { fprintf(stderr, "dane_query_tlsa: %s\n", dane_strerror(ret)); exit(1); } entries = dane_query_entries(q); for (i = 0; i < entries; i++) { ret = dane_query_data(q, i, &usage, &type, &match, &data); if (ret < 0) { fprintf(stderr, "dane_query_data: %s\n", dane_strerror(ret)); exit(1); } size = buffer_size; ret = gnutls_hex_encode(&data, (void *) buffer, &size); if (ret < 0) { fprintf(stderr, "gnutls_hex_encode: %s\n", dane_strerror(ret)); exit(1); } if (entries > 1) printf("\nEntry %d:\n", i + 1); fprintf(outfile, "_%u._%s.%s. IN TLSA ( %.2x %.2x %.2x %s )\n", port, proto, host, usage, type, match, buffer); printf("Certificate usage: %s (%.2x)\n", dane_cert_usage_name(usage), usage); printf("Certificate type: %s (%.2x)\n", dane_cert_type_name(type), type); printf("Contents: %s (%.2x)\n", dane_match_type_name(match), match); printf("Data: %s\n", buffer); /* Verify the DANE data */ if (cinfo->cert) { gnutls_x509_crt_t *clist; unsigned int clist_size, status; ret = gnutls_load_file(cinfo->cert, &file); if (ret < 0) { fprintf(stderr, "gnutls_load_file: %s\n", gnutls_strerror(ret)); exit(1); } ret = gnutls_x509_crt_list_import2(&clist, &clist_size, &file, cinfo-> incert_format, 0); if (ret < 0) { fprintf(stderr, "gnutls_x509_crt_list_import2: %s\n", gnutls_strerror(ret)); exit(1); } if (clist_size > 0) { gnutls_datum_t certs[clist_size]; gnutls_datum_t out; unsigned int i; for (i = 0; i < clist_size; i++) { ret = gnutls_x509_crt_export2(clist [i], GNUTLS_X509_FMT_DER, &certs [i]); if (ret < 0) { fprintf(stderr, "gnutls_x509_crt_export2: %s\n", gnutls_strerror (ret)); exit(1); } } ret = dane_verify_crt(s, certs, clist_size, GNUTLS_CRT_X509, host, proto, port, 0, vflags, &status); if (ret < 0) { fprintf(stderr, "dane_verify_crt: %s\n", dane_strerror(ret)); exit(1); } ret = dane_verification_status_print(status, &out, 0); if (ret < 0) { fprintf(stderr, "dane_verification_status_print: %s\n", dane_strerror(ret)); exit(1); } printf("\nVerification: %s\n", out.data); gnutls_free(out.data); if (status != 0) retcode = 1; for (i = 0; i < clist_size; i++) { gnutls_free(certs[i].data); gnutls_x509_crt_deinit(clist[i]); } gnutls_free(clist); } } else { fprintf(stderr, "\nCertificate was not verified. Use --load-certificate.\n"); } } dane_query_deinit(q); dane_state_deinit(s); exit(retcode); #else fprintf(stderr, "This functionality was disabled (GnuTLS was not compiled with support for DANE).\n"); return; #endif }