Esempio n. 1
0
int Cert::tmpfile_export(QString& filename)
{
    gnutls_datum_t out;
    int ret = gnutls_x509_crt_export2(this->crt, GNUTLS_X509_FMT_PEM, &out);
    if (ret < 0) {
        this->last_err = gnutls_strerror(ret);
        return -1;
    }

    QByteArray qa;
    qa.append((const char*)out.data, out.size);
    gnutls_free(out.data);

    tmpfile.resize(0);
    filename = TMP_CERT_PREFIX;
    tmpfile.setFileTemplate(filename);

    tmpfile.open();
    ret = tmpfile.write(qa);
    tmpfile.close();
    if (ret == -1) {
        return -1;
    }
    filename = tmpfile.fileName();

    return 0;
}
Esempio n. 2
0
int Cert::data_export(QByteArray& data)
{
    data.clear();

    if (this->imported != true) {
        return -1;
    }

    gnutls_datum_t raw;
    int ret = gnutls_x509_crt_export2(this->crt, GNUTLS_X509_FMT_PEM, &raw);
    if (ret < 0) {
        this->last_err = gnutls_strerror(ret);
        return -1;
    }

    data = QByteArray((char*)raw.data, raw.size);
    gnutls_free(raw.data);
    return 0;
}
Esempio n. 3
0
int pkcs11_override_cert_exts(struct pkcs11_session_info *sinfo, gnutls_datum_t *spki, gnutls_datum_t *der)
{
	int ret;
	gnutls_datum_t new_der = {NULL, 0};
	struct ck_attribute a[2];
	struct ck_attribute b[1];
	unsigned long count;
	unsigned ext_data_size = der->size;
	uint8_t *ext_data = NULL;
	ck_object_class_t class = -1;
	gnutls_x509_crt_t crt = NULL;
	unsigned finalize = 0;
	ck_rv_t rv;
	ck_object_handle_t obj;

	/* retrieve the extensions */
	class = CKO_X_CERTIFICATE_EXTENSION;
	a[0].type = CKA_CLASS;
	a[0].value = &class;
	a[0].value_len = sizeof class;

	a[1].type = CKA_PUBLIC_KEY_INFO;
	a[1].value = spki->data;
	a[1].value_len = spki->size;

	rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a, 2);
	if (rv != CKR_OK) {
		gnutls_assert();
		_gnutls_debug_log
		    ("p11: FindObjectsInit failed for cert extensions.\n");
		ret = pkcs11_rv_to_err(rv);
		goto cleanup;
	}
	finalize = 1;

	rv = pkcs11_find_objects(sinfo->module, sinfo->pks, &obj, 1, &count);
	if (rv == CKR_OK && count == 1) {
		ext_data = gnutls_malloc(ext_data_size);
		if (ext_data == NULL) {
			gnutls_assert();
			ret = GNUTLS_E_MEMORY_ERROR;
			goto cleanup;
		}

		ret = gnutls_x509_crt_init(&crt);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = gnutls_x509_crt_import(crt, der, GNUTLS_X509_FMT_DER);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		do {

			b[0].type = CKA_VALUE;
			b[0].value = ext_data;
			b[0].value_len = ext_data_size;

			if (pkcs11_get_attribute_value
			    (sinfo->module, sinfo->pks, obj, b, 1) == CKR_OK) {
				gnutls_datum_t data = { b[0].value, b[0].value_len };

				ret = override_ext(crt, &data);
				if (ret < 0) {
					gnutls_assert();
					goto cleanup;
				}
			}
		} while (pkcs11_find_objects(sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1);

		/* overwrite the old certificate with the new */
		ret = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &new_der);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		gnutls_free(der->data);
		der->data = new_der.data;
		der->size = new_der.size;
	}

	ret = 0;
 cleanup:
 	if (crt != NULL)
	 	gnutls_x509_crt_deinit(crt);
	if (finalize != 0)
		pkcs11_find_objects_final(sinfo);
 	gnutls_free(ext_data);
 	return ret;

}
Esempio n. 4
0
void doit(void)
{
	gnutls_x509_privkey_t pkey;
	gnutls_x509_crt_t crt;
	gnutls_x509_crt_t crt2;
	const char *err = NULL;
	gnutls_datum_t out;
	size_t s = 0;
	int ret;

	ret = global_init();
	if (ret < 0)
		fail("global_init\n");

	gnutls_global_set_time_function(mytime);
	gnutls_global_set_log_function(tls_log_func);
	if (debug)
		gnutls_global_set_log_level(4711);

	ret = gnutls_x509_crt_init(&crt);
	if (ret != 0)
		fail("gnutls_x509_crt_init\n");

	ret = gnutls_x509_crt_init(&crt2);
	if (ret != 0)
		fail("gnutls_x509_crt_init\n");

	ret = gnutls_x509_crt_import(crt2, &server_ecc_cert, GNUTLS_X509_FMT_PEM);
	if (ret != 0)
		fail("gnutls_x509_crt_import\n");

	ret = gnutls_x509_privkey_init(&pkey);
	if (ret != 0)
		fail("gnutls_x509_privkey_init\n");

	ret = gnutls_x509_privkey_import(pkey, &key_dat, GNUTLS_X509_FMT_PEM);
	if (ret != 0)
		fail("gnutls_x509_privkey_import\n");

	/* Setup CRT */

	ret = gnutls_x509_crt_set_version(crt, 3);
	if (ret != 0)
		fail("gnutls_x509_crt_set_version\n");

	ret = gnutls_x509_crt_set_serial(crt, "\x0a\x11\x00", 3);
	if (ret != 0)
		fail("gnutls_x509_crt_set_serial\n");

	ret = gnutls_x509_crt_set_expiration_time(crt, -1);
	if (ret != 0)
		fail("error\n");

	ret = gnutls_x509_crt_set_activation_time(crt, mytime(0));
	if (ret != 0)
		fail("error\n");

	ret = gnutls_x509_crt_set_key(crt, pkey);
	if (ret != 0)
		fail("gnutls_x509_crt_set_key\n");

	ret = gnutls_x509_crt_set_basic_constraints(crt, 0, -1);
	if (ret < 0) {
		fail("error\n");
	}

	ret = gnutls_x509_crt_set_key_usage(crt, GNUTLS_KEY_DIGITAL_SIGNATURE);
	if (ret != 0)
		fail("gnutls_x509_crt_set_key_usage %d\n", ret);

	ret = gnutls_x509_crt_set_dn(crt, "o = none to\\, mention,cn = nikos", &err);
	if (ret < 0) {
		fail("gnutls_x509_crt_set_dn: %s, %s\n", gnutls_strerror(ret), err);
	}


	ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME,
						   "foo", 3, 1);
	if (ret != 0)
		fail("gnutls_x509_crt_set_subject_alt_name\n");

	ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_RFC822NAME,
						   "*****@*****.**", strlen("*****@*****.**"), 1);
	if (ret != 0)
		fail("gnutls_x509_crt_set_subject_alt_name\n");

	ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_RFC822NAME,
						   "ινβάλιντ@bar.org", strlen("ινβάλιντ@bar.org"), 1);
	if (ret != GNUTLS_E_INVALID_UTF8_EMAIL)
		fail("gnutls_x509_crt_set_subject_alt_name\n");


	ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_IPADDRESS,
						   "\xc1\x5c\x96\x3", 4, 1);
	if (ret != 0)
		fail("gnutls_x509_crt_set_subject_alt_name\n");

	ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_IPADDRESS,
						   "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 16, 1);
	if (ret != 0)
		fail("gnutls_x509_crt_set_subject_alt_name\n");

	ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME,
						   "apa", 3, 0);
	if (ret != 0)
		fail("gnutls_x509_crt_set_subject_alt_name\n");

	ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME,
						   "απαλό.com", strlen("απαλό.com"), 1);
	if (ret != 0)
		fail("gnutls_x509_crt_set_subject_alt_name\n");

#ifdef HAVE_LIBIDN
	ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_RFC822NAME,
						   "test@νίκο.org", strlen("test@νίκο.org"), 1);
	if (ret != 0)
		fail("gnutls_x509_crt_set_subject_alt_name\n");
#endif

	s = 0;
	ret = gnutls_x509_crt_get_key_purpose_oid(crt, 0, NULL, &s, NULL);
	if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
		fail("gnutls_x509_crt_get_key_purpose_oid %d\n", ret);

	s = 0;
	ret =
	    gnutls_x509_crt_set_key_purpose_oid(crt,
						GNUTLS_KP_TLS_WWW_SERVER,
						0);
	if (ret != 0)
		fail("gnutls_x509_crt_set_key_purpose_oid %d\n", ret);

	s = 0;
	ret = gnutls_x509_crt_get_key_purpose_oid(crt, 0, NULL, &s, NULL);
	if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
		fail("gnutls_x509_crt_get_key_purpose_oid %d\n", ret);

	s = 0;
	ret =
	    gnutls_x509_crt_set_key_purpose_oid(crt,
						GNUTLS_KP_TLS_WWW_CLIENT,
						1);
	if (ret != 0)
		fail("gnutls_x509_crt_set_key_purpose_oid2 %d\n", ret);

	ret = gnutls_x509_crt_set_issuer_dn(crt, "cn = my CA, o = big\\, and one", &err);
	if (ret < 0) {
		fail("gnutls_x509_crt_set_issuer_dn: %s, %s\n", gnutls_strerror(ret), err);
	}

	ret = gnutls_x509_crt_sign2(crt, crt, pkey, GNUTLS_DIG_SHA256, 0);
	if (ret < 0)
		fail("gnutls_x509_crt_sign2: %s\n", gnutls_strerror(ret));



	ret = gnutls_x509_crt_print(crt, GNUTLS_CRT_PRINT_FULL, &out);
	if (ret != 0)
		fail("gnutls_x509_crt_print\n");
	if (debug)
		printf("crt: %.*s\n", out.size, out.data);
	gnutls_free(out.data);


	s = 0;
	ret = gnutls_x509_crt_get_extension_info(crt, 0, NULL, &s, NULL);
	if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
		fail("gnutls_x509_crt_get_extension_info2: %s\n", strerror(ret));

	s = 0;
	ret = gnutls_x509_crt_get_extension_data(crt, 0, NULL, &s);
	if (ret != 0)
		fail("gnutls_x509_crt_get_extension_data: %s\n", strerror(ret));

	ret = gnutls_x509_crt_get_raw_issuer_dn(crt, &out);
	if (ret < 0 || out.size == 0)
		fail("gnutls_x509_crt_get_raw_issuer_dn: %s\n", gnutls_strerror(ret));

	if (out.size != 45 ||
	    memcmp(out.data, "\x30\x2b\x31\x0e\x30\x0c\x06\x03\x55\x04\x03\x13\x05\x6e\x69\x6b\x6f\x73\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x6e\x6f\x6e\x65\x20\x74\x6f\x2c\x20\x6d\x65\x6e\x74\x69\x6f\x6e", 45) != 0) {
		hexprint(out.data, out.size);
		fail("issuer DN comparison failed\n");
	}
	gnutls_free(out.data);

	ret = gnutls_x509_crt_get_raw_dn(crt, &out);
	if (ret < 0 || out.size == 0)
		fail("gnutls_x509_crt_get_raw_dn: %s\n", gnutls_strerror(ret));

	if (out.size != 45 ||
	    memcmp(out.data, "\x30\x2b\x31\x0e\x30\x0c\x06\x03\x55\x04\x03\x13\x05\x6e\x69\x6b\x6f\x73\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x6e\x6f\x6e\x65\x20\x74\x6f\x2c\x20\x6d\x65\x6e\x74\x69\x6f\x6e", 45) != 0) {
		fail("DN comparison failed\n");
	}
	gnutls_free(out.data);

	ret = gnutls_x509_crt_equals(crt, crt);
	if (ret == 0) {
		fail("equality test failed\n");
	}

	ret = gnutls_x509_crt_equals(crt, crt2);
	if (ret != 0) {
		fail("equality test failed\n");
	}
	assert(gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_PEM, &out) >= 0);

#ifdef HAVE_LIBIDN
	assert(out.size == saved_crt.size);
	assert(memcmp(out.data, saved_crt.data, out.size)==0);
#endif

	gnutls_free(out.data);

	gnutls_x509_crt_deinit(crt);
	gnutls_x509_crt_deinit(crt2);
	gnutls_x509_privkey_deinit(pkey);

	gnutls_global_deinit();
}
Esempio n. 5
0
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
}
Esempio n. 6
0
void doit(void)
{
	gnutls_certificate_credentials_t x509_cred;
	int ret;
	unsigned int i;
	gnutls_x509_crt_t issuer;
	gnutls_x509_crt_t list[LIST_SIZE];
	char dn[128];
	size_t dn_size;
	unsigned int list_size;
	size_t buf_size;

	gnutls_x509_privkey_t get_key;
	gnutls_x509_crt_t *get_crts;
	unsigned n_get_crts;
	gnutls_datum_t get_datum, chain_datum[2] = {server_ca3_cert, subca3_cert};
	gnutls_x509_trust_list_t trust_list;
	gnutls_x509_trust_list_iter_t trust_iter;
	gnutls_x509_crt_t get_ca_crt;
	unsigned n_get_ca_crts;

	/* this must be called once in the program
	 */
	global_init();

	gnutls_global_set_log_function(tls_log_func);
	if (debug)
		gnutls_global_set_log_level(6);

	gnutls_certificate_allocate_credentials(&x509_cred);
	gnutls_certificate_set_x509_trust_mem(x509_cred, &ca3_cert,
					      GNUTLS_X509_FMT_PEM);

	gnutls_certificate_set_x509_key_mem(x509_cred, &server_ca3_cert_chain,
					    &server_ca3_key,
					    GNUTLS_X509_FMT_PEM);

	/* test for gnutls_certificate_get_issuer() */

	/* check whether gnutls_x509_crt_list_import will fail if given a single
	 * certificate */
	list_size = LIST_SIZE;
	ret =
	    gnutls_x509_crt_list_import(list, &list_size, &ca3_cert,
					GNUTLS_X509_FMT_PEM,
					GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED);
	if (ret < 0)
		fail("gnutls_x509_crt_list_import (failed with a single cert)");
	gnutls_x509_crt_deinit(list[0]);

	list_size = LIST_SIZE;
	ret =
	    gnutls_x509_crt_list_import(list, &list_size, &cli_ca3_cert_chain,
					GNUTLS_X509_FMT_PEM,
					GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED);
	if (ret < 0)
		fail("gnutls_x509_crt_list_import");

	ret =
	    gnutls_certificate_get_issuer(x509_cred, list[list_size-1], &issuer, 0);
	if (ret < 0)
		fail("gnutls_certificate_get_isser");

	ret =
	    gnutls_certificate_get_issuer(x509_cred, list[list_size-1], &issuer, GNUTLS_TL_GET_COPY);
	if (ret < 0)
		fail("gnutls_certificate_get_isser");

	dn_size = sizeof(dn);
	ret = gnutls_x509_crt_get_dn(issuer, dn, &dn_size);
	if (ret < 0)
		fail("gnutls_certificate_get_dn");
	gnutls_x509_crt_deinit(issuer);

	if (dn_size != strlen(dn)) {
		fail("gnutls_x509_crt_get_dn: lengths don't match\n");
		exit(1);
	}

	if (debug)
		fprintf(stderr, "Issuer's DN: %s\n", dn);

	/* test the getter functions of gnutls_certificate_credentials_t */

	ret =
	    gnutls_certificate_get_x509_key(x509_cred, 0, &get_key);
	if (ret < 0)
		fail("gnutls_certificate_get_x509_key");

	ret =
	    gnutls_x509_privkey_export2(get_key,
					GNUTLS_X509_FMT_PEM,
					&get_datum);
	if (ret < 0)
		fail("gnutls_x509_privkey_export2");

	if (get_datum.size != server_ca3_key.size ||
	    memcmp(get_datum.data, server_ca3_key.data, get_datum.size) != 0) {
		fail(
		    "exported key %u vs. %u\n\n%s\n\nvs.\n\n%s",
		    get_datum.size, server_ca3_key.size,
		    get_datum.data, server_ca3_key.data);
	}

	if (strlen((char*)get_datum.data) != get_datum.size) {
		fail("exported key %u vs. %u\n\n%s\n",
		     get_datum.size, (unsigned)strlen((char*)get_datum.data),
		     get_datum.data);
	}

	gnutls_free(get_datum.data);

	buf_size = sizeof(buf);
	ret =
	    gnutls_x509_privkey_export(get_key,
					GNUTLS_X509_FMT_PEM,
					buf, &buf_size);
	if (ret < 0)
		fail("gnutls_x509_privkey_export");

	if (buf_size != get_datum.size ||
	    buf_size != strlen(buf) ||
	    memcmp(buf, server_ca3_key.data, buf_size) != 0) {
		fail(
		    "exported key %u vs. %u\n\n%s\n\nvs.\n\n%s",
		    (int)buf_size, server_ca3_key.size,
		    buf, server_ca3_key.data);
	}

	ret =
	    gnutls_certificate_get_x509_crt(x509_cred, 0, &get_crts, &n_get_crts);
	if (ret < 0)
		fail("gnutls_certificate_get_x509_crt");
	if (n_get_crts != 2)
		fail("gnutls_certificate_get_x509_crt: n_crts != 2");

	for (i = 0; i < n_get_crts; i++) {
		ret =
			gnutls_x509_crt_export2(get_crts[i],
						GNUTLS_X509_FMT_PEM,
						&get_datum);
		if (ret < 0)
			fail("gnutls_x509_crt_export2");

		if (get_datum.size != chain_datum[i].size ||
		    memcmp(get_datum.data, chain_datum[i].data, get_datum.size) != 0) {
			fail(
				"exported certificate %u vs. %u\n\n%s\n\nvs.\n\n%s",
				get_datum.size, chain_datum[i].size,
				get_datum.data, chain_datum[i].data);
		}

		gnutls_free(get_datum.data);
	}

	gnutls_certificate_get_trust_list(x509_cred, &trust_list);

	n_get_ca_crts = 0;
	trust_iter = NULL;
	while (gnutls_x509_trust_list_iter_get_ca(trust_list,
						  &trust_iter,
						  &get_ca_crt) !=
		GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
		ret =
		    gnutls_x509_crt_export2(get_ca_crt,
					    GNUTLS_X509_FMT_PEM,
					    &get_datum);
		if (ret < 0)
			fail("gnutls_x509_crt_export2");

		if (get_datum.size != ca3_cert.size ||
		    memcmp(get_datum.data, ca3_cert.data, get_datum.size) != 0) {
			fail(
			    "exported CA certificate %u vs. %u\n\n%s\n\nvs.\n\n%s",
			    get_datum.size, ca3_cert.size,
			    get_datum.data, ca3_cert.data);
		}

		gnutls_x509_crt_deinit(get_ca_crt);
		gnutls_free(get_datum.data);

		++n_get_ca_crts;
	}

	if (n_get_ca_crts != 1)
		fail("gnutls_x509_trust_list_iter_get_ca: n_cas != 1");
	if (trust_iter != NULL)
		fail("gnutls_x509_trust_list_iter_get_ca: iterator not NULL after iteration");

	gnutls_x509_privkey_deinit(get_key);
	for (i = 0; i < n_get_crts; i++)
		gnutls_x509_crt_deinit(get_crts[i]);
	gnutls_free(get_crts);

	for (i = 0; i < list_size; i++)
		gnutls_x509_crt_deinit(list[i]);
	gnutls_certificate_free_credentials(x509_cred);

	gnutls_global_deinit();

	if (debug)
		success("success");
}
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");
	}
}
Esempio n. 8
0
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
}
Esempio n. 9
0
void doit(void)
{
	gnutls_x509_privkey_t pkey;
	gnutls_x509_crt_t crt;
	gnutls_x509_crt_t crt2;
	const char *err = NULL;
	unsigned char buf[64];
	gnutls_datum_t out;
	size_t s = 0;
	int ret;

	ret = global_init();
	if (ret < 0)
		fail("global_init\n");

	gnutls_global_set_time_function(mytime);
	gnutls_global_set_log_function(tls_log_func);
	if (debug)
		gnutls_global_set_log_level(4711);

	ret = gnutls_x509_crt_init(&crt);
	if (ret != 0)
		fail("gnutls_x509_crt_init\n");

	ret = gnutls_x509_crt_init(&crt2);
	if (ret != 0)
		fail("gnutls_x509_crt_init\n");

	ret = gnutls_x509_crt_import(crt2, &server_ecc_cert, GNUTLS_X509_FMT_PEM);
	if (ret != 0)
		fail("gnutls_x509_crt_import\n");

	ret = gnutls_x509_privkey_init(&pkey);
	if (ret != 0)
		fail("gnutls_x509_privkey_init\n");

	ret = gnutls_x509_privkey_import(pkey, &key_dat, GNUTLS_X509_FMT_PEM);
	if (ret != 0)
		fail("gnutls_x509_privkey_import\n");

	/* Setup CRT */

	ret = gnutls_x509_crt_set_version(crt, 3);
	if (ret != 0)
		fail("gnutls_x509_crt_set_version\n");

	ret = gnutls_x509_crt_set_serial(crt, "\x0a\x11\x00", 3);
	if (ret != 0)
		fail("gnutls_x509_crt_set_serial\n");

	ret = gnutls_x509_crt_set_expiration_time(crt, -1);
	if (ret != 0)
		fail("error\n");

	ret = gnutls_x509_crt_set_activation_time(crt, mytime(0));
	if (ret != 0)
		fail("error\n");

	ret = gnutls_x509_crt_set_key(crt, pkey);
	if (ret != 0)
		fail("gnutls_x509_crt_set_key\n");

	ret = gnutls_x509_crt_set_basic_constraints(crt, 0, -1);
	if (ret < 0) {
		fail("error\n");
	}

	ret = gnutls_x509_crt_set_key_usage(crt, GNUTLS_KEY_DIGITAL_SIGNATURE);
	if (ret != 0)
		fail("gnutls_x509_crt_set_key_usage %d\n", ret);

	ret = gnutls_x509_crt_set_dn(crt, "o = none to\\, mention,cn = nikos", &err);
	if (ret < 0) {
		fail("gnutls_x509_crt_set_dn: %s, %s\n", gnutls_strerror(ret), err);
	}


	ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME,
						   "foo", 3, 1);
	if (ret != 0)
		fail("gnutls_x509_crt_set_subject_alt_name\n");

	ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_RFC822NAME,
						   "*****@*****.**", strlen("*****@*****.**"), 1);
	if (ret != 0)
		fail("gnutls_x509_crt_set_subject_alt_name\n");

	ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_RFC822NAME,
						   "ινβάλιντ@bar.org", strlen("ινβάλιντ@bar.org"), 1);
	if (ret != GNUTLS_E_INVALID_UTF8_EMAIL)
		fail("gnutls_x509_crt_set_subject_alt_name\n");


	ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_IPADDRESS,
						   "\xc1\x5c\x96\x3", 4, 1);
	if (ret != 0)
		fail("gnutls_x509_crt_set_subject_alt_name\n");

	ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_IPADDRESS,
						   "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 16, 1);
	if (ret != 0)
		fail("gnutls_x509_crt_set_subject_alt_name\n");

	ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME,
						   "apa", 3, 0);
	if (ret != 0)
		fail("gnutls_x509_crt_set_subject_alt_name\n");

	ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_DNSNAME,
						   "απαλό.com", strlen("απαλό.com"), 1);
#if defined(HAVE_LIBIDN2) || defined(HAVE_LIBIDN)
	if (ret != 0)
		fail("gnutls_x509_crt_set_subject_alt_name: %s\n", gnutls_strerror(ret));

	ret = gnutls_x509_crt_set_subject_alt_name(crt, GNUTLS_SAN_RFC822NAME,
						   "test@νίκο.org", strlen("test@νίκο.org"), 1);
	if (ret != 0)
		fail("gnutls_x509_crt_set_subject_alt_name\n");
#else
	if (ret != GNUTLS_E_UNIMPLEMENTED_FEATURE)
		fail("gnutls_x509_crt_set_subject_alt_name: %s\n", gnutls_strerror(ret));
#endif

	s = 0;
	ret = gnutls_x509_crt_get_key_purpose_oid(crt, 0, NULL, &s, NULL);
	if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
		fail("gnutls_x509_crt_get_key_purpose_oid %d\n", ret);

	s = 0;
	ret =
	    gnutls_x509_crt_set_key_purpose_oid(crt,
						GNUTLS_KP_TLS_WWW_SERVER,
						0);
	if (ret != 0)
		fail("gnutls_x509_crt_set_key_purpose_oid %d\n", ret);

	s = 0;
	ret = gnutls_x509_crt_get_key_purpose_oid(crt, 0, NULL, &s, NULL);
	if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
		fail("gnutls_x509_crt_get_key_purpose_oid %d\n", ret);

	s = 0;
	ret =
	    gnutls_x509_crt_set_key_purpose_oid(crt,
						GNUTLS_KP_TLS_WWW_CLIENT,
						1);
	if (ret != 0)
		fail("gnutls_x509_crt_set_key_purpose_oid2 %d\n", ret);

	/* in the end this will be ignored as the issuer will be set
	 * by gnutls_x509_crt_sign2() */
	ret = gnutls_x509_crt_set_issuer_dn(crt, "cn = my CA, o = big\\, and one", &err);
	if (ret < 0) {
		fail("gnutls_x509_crt_set_issuer_dn: %s, %s\n", gnutls_strerror(ret), err);
	}

#define ISSUER_UNIQUE_ID "\x00\x01\x02\x03"
#define SUBJECT_UNIQUE_ID "\x04\x03\x02\x01"
	ret = gnutls_x509_crt_set_issuer_unique_id(crt, ISSUER_UNIQUE_ID, sizeof(ISSUER_UNIQUE_ID)-1);
	if (ret < 0)
		fail("error: %s\n", gnutls_strerror(ret));

	ret = gnutls_x509_crt_set_subject_unique_id(crt, SUBJECT_UNIQUE_ID, sizeof(SUBJECT_UNIQUE_ID)-1);
	if (ret < 0)
		fail("error: %s\n", gnutls_strerror(ret));

	/* Sign and finalize the certificate */
	ret = gnutls_x509_crt_sign2(crt, crt, pkey, GNUTLS_DIG_SHA256, 0);
	if (ret < 0)
		fail("gnutls_x509_crt_sign2: %s\n", gnutls_strerror(ret));


	ret = gnutls_x509_crt_print(crt, GNUTLS_CRT_PRINT_FULL, &out);
	if (ret != 0)
		fail("gnutls_x509_crt_print\n");
	if (debug)
		printf("crt: %.*s\n", out.size, out.data);
	gnutls_free(out.data);

	/* Verify whether selected input is present */
	s = 0;
	ret = gnutls_x509_crt_get_extension_info(crt, 0, NULL, &s, NULL);
	if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
		fail("gnutls_x509_crt_get_extension_info2: %s\n", strerror(ret));

	s = 0;
	ret = gnutls_x509_crt_get_extension_data(crt, 0, NULL, &s);
	if (ret != 0)
		fail("gnutls_x509_crt_get_extension_data: %s\n", strerror(ret));

	ret = gnutls_x509_crt_get_raw_issuer_dn(crt, &out);
	if (ret < 0 || out.size == 0)
		fail("gnutls_x509_crt_get_raw_issuer_dn: %s\n", gnutls_strerror(ret));

	if (out.size != 45 ||
	    memcmp(out.data, "\x30\x2b\x31\x0e\x30\x0c\x06\x03\x55\x04\x03\x13\x05\x6e\x69\x6b\x6f\x73\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x6e\x6f\x6e\x65\x20\x74\x6f\x2c\x20\x6d\x65\x6e\x74\x69\x6f\x6e", 45) != 0) {
		hexprint(out.data, out.size);
		fail("issuer DN comparison failed\n");
	}
	gnutls_free(out.data);

	s = sizeof(buf);
	ret = gnutls_x509_crt_get_issuer_unique_id(crt, (void*)buf, &s);
	if (ret < 0)
		fail("error: %s\n", gnutls_strerror(ret));

	if (s != sizeof(ISSUER_UNIQUE_ID)-1 ||
		memcmp(buf, ISSUER_UNIQUE_ID, s) != 0) {
		fail("issuer unique id comparison failed\n");
	}

	s = sizeof(buf);
	ret = gnutls_x509_crt_get_subject_unique_id(crt, (void*)buf, &s);
	if (ret < 0)
		fail("error: %s\n", gnutls_strerror(ret));

	if (s != sizeof(SUBJECT_UNIQUE_ID)-1 ||
		memcmp(buf, SUBJECT_UNIQUE_ID, s) != 0) {
		fail("subject unique id comparison failed\n");
	}

	ret = gnutls_x509_crt_get_raw_dn(crt, &out);
	if (ret < 0 || out.size == 0)
		fail("gnutls_x509_crt_get_raw_dn: %s\n", gnutls_strerror(ret));

	if (out.size != 45 ||
	    memcmp(out.data, "\x30\x2b\x31\x0e\x30\x0c\x06\x03\x55\x04\x03\x13\x05\x6e\x69\x6b\x6f\x73\x31\x19\x30\x17\x06\x03\x55\x04\x0a\x13\x10\x6e\x6f\x6e\x65\x20\x74\x6f\x2c\x20\x6d\x65\x6e\x74\x69\x6f\x6e", 45) != 0) {
		fail("DN comparison failed\n");
	}
	gnutls_free(out.data);

	ret = gnutls_x509_crt_equals(crt, crt);
	if (ret == 0) {
		fail("equality test failed\n");
	}

	ret = gnutls_x509_crt_equals(crt, crt2);
	if (ret != 0) {
		fail("equality test failed\n");
	}
	assert(gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_PEM, &out) >= 0);

	if (debug)
		fprintf(stderr, "%s\n", out.data);
#if defined(HAVE_LIBIDN2)
	assert(out.size == saved_crt.size);
	assert(memcmp(out.data, saved_crt.data, out.size)==0);
#endif

	gnutls_free(out.data);

	gnutls_x509_crt_deinit(crt);
	gnutls_x509_crt_deinit(crt2);
	gnutls_x509_privkey_deinit(pkey);

	gnutls_global_deinit();
}
Esempio n. 10
0
/**
 * gnutls_system_key_add_x509:
 * @crt: the certificate to be added
 * @privkey: the key to be added
 * @label: the friendly name to describe the key
 * @cert_url: if non-NULL it will contain an allocated value with the certificate URL
 * @key_url: if non-NULL it will contain an allocated value with the key URL
 *
 * This function will added the given key and certificate pair,
 * to the system list.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.4.0
 **/
int gnutls_system_key_add_x509(gnutls_x509_crt_t crt,
			       gnutls_x509_privkey_t privkey, const char *label,
			       char **cert_url, char **key_url)
{
	HCERTSTORE store = NULL;
	CRYPT_DATA_BLOB pfx;
	gnutls_datum_t _pfx = { NULL, 0 };
	gnutls_pkcs12_t p12 = NULL;
	gnutls_pkcs12_bag_t bag1 = NULL, bag2 = NULL;
	uint8_t id[MAX_WID_SIZE];
	size_t id_size;
	gnutls_datum_t kid;
	int ret;

	if (ncrypt_init == 0)
		return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);

	if (label == NULL)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	id_size = sizeof(id);
	ret = gnutls_x509_crt_get_key_id(crt, 0, id, &id_size);
	if (ret < 0)
		return gnutls_assert_val(ret);

	kid.data = id;
	kid.size = id_size;

	/* the idea: import the cert and private key into PKCS #12
	 * format, export it into pfx, and import it into store */
	ret = gnutls_pkcs12_init(&p12);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret = gnutls_pkcs12_bag_init(&bag1);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = gnutls_pkcs12_bag_set_crt(bag1, crt);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = gnutls_pkcs12_bag_set_key_id(bag1, 0, &kid);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	if (label)
		gnutls_pkcs12_bag_set_friendly_name(bag1, 0, label);

	ret = gnutls_pkcs12_bag_init(&bag2);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = gnutls_pkcs12_bag_set_privkey(bag2, privkey, NULL, 0);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = gnutls_pkcs12_bag_set_key_id(bag2, 0, &kid);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	if (label)
		gnutls_pkcs12_bag_set_friendly_name(bag2, 0, label);

	ret = gnutls_pkcs12_set_bag(p12, bag1);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = gnutls_pkcs12_set_bag(p12, bag2);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = gnutls_pkcs12_generate_mac(p12, "123456");
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = gnutls_pkcs12_export2(p12, GNUTLS_X509_FMT_DER, &_pfx);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	pfx.cbData = _pfx.size;
	pfx.pbData = _pfx.data;

	store = PFXImportCertStore(&pfx, L"123456", 0);
	if (store == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_INVALID_REQUEST;
		goto cleanup;
	}

	if (cert_url || key_url) {
		unsigned char sha[20];
		CRYPT_HASH_BLOB blob;
		const CERT_CONTEXT *cert = NULL;
		gnutls_datum_t data;

		ret = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &data);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret =
		    gnutls_hash_fast(GNUTLS_DIG_SHA1, data.data, data.size,
				     sha);
		gnutls_free(data.data);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		blob.cbData = sizeof(sha);
		blob.pbData = sha;

		cert = CertFindCertificateInStore(store,
						  X509_ASN_ENCODING,
						  0,
						  CERT_FIND_SHA1_HASH,
						  &blob, NULL);

		if (cert == NULL) {
			gnutls_assert();
			ret = GNUTLS_E_KEY_IMPORT_FAILED;
			goto cleanup;
		}

		ret = get_win_urls(cert, cert_url, key_url, NULL, NULL);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}

	ret = 0;

 cleanup:
	if (p12 != NULL)
		gnutls_pkcs12_deinit(p12);
	if (bag1 != NULL)
		gnutls_pkcs12_bag_deinit(bag1);
	if (bag2 != NULL)
		gnutls_pkcs12_bag_deinit(bag2);
	if (store != NULL)
		CertCloseStore(store, 0);
	gnutls_free(_pfx.data);
	return ret;
}