Exemple #1
0
/**
 * ntfs_pkcs12_extract_rsa_key
 */
static ntfs_rsa_private_key ntfs_pkcs12_extract_rsa_key(u8 *pfx, int pfx_size,
		char *password, char *thumbprint, int thumbprint_size,
		NTFS_DF_TYPES *df_type)
{
	int err, bag_index, flags;
	gnutls_datum_t dpfx, dkey;
	gnutls_pkcs12_t pkcs12 = NULL;
	gnutls_pkcs12_bag_t bag = NULL;
	gnutls_x509_privkey_t pkey = NULL;
	gnutls_x509_crt_t crt = NULL;
	ntfs_rsa_private_key rsa_key = NULL;
	char purpose_oid[100];
	size_t purpose_oid_size = sizeof(purpose_oid);
	int oid_index;
	size_t tp_size = thumbprint_size;
	BOOL have_thumbprint = FALSE;

	*df_type = DF_TYPE_UNKNOWN;
	/* Create a pkcs12 structure. */
	err = gnutls_pkcs12_init(&pkcs12);
	if (err) {
		ntfs_log_error("Failed to initialize PKCS#12 structure: %s\n",
				gnutls_strerror(err));
		return NULL;
	}
	/* Convert the PFX file (DER format) to native pkcs12 format. */
	dpfx.data = pfx;
	dpfx.size = pfx_size;
	err = gnutls_pkcs12_import(pkcs12, &dpfx, GNUTLS_X509_FMT_DER, 0);
	if (err) {
		ntfs_log_error("Failed to convert the PFX file from DER to "
				"native PKCS#12 format: %s\n",
				gnutls_strerror(err));
		goto err;
	}
	/*
	 * Verify that the password is correct and that the key file has not
	 * been tampered with.  Note if the password has zero length and the
	 * verification fails, retry with password set to NULL.  This is needed
	 * to get passwordless .pfx files generated with Windows XP SP1 (and
	 * probably earlier versions of Windows) to work.
	 */
retry_verify:
	err = gnutls_pkcs12_verify_mac(pkcs12, password);
	if (err) {
		if (err == GNUTLS_E_MAC_VERIFY_FAILED &&
				password && !strlen(password)) {
			password = NULL;
			goto retry_verify;
		}
		ntfs_log_error("Failed to verify the MAC: %s  Is the "
				"password correct?\n", gnutls_strerror(err));
		goto err;
	}
	for (bag_index = 0; ; bag_index++) {
		err = gnutls_pkcs12_bag_init(&bag);
		if (err) {
			ntfs_log_error("Failed to initialize PKCS#12 Bag "
					"structure: %s\n",
					gnutls_strerror(err));
			goto err;
		}
		err = gnutls_pkcs12_get_bag(pkcs12, bag_index, bag);
		if (err) {
			if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
				err = 0;
				break;
			}
			ntfs_log_error("Failed to obtain Bag from PKCS#12 "
					"structure: %s\n",
					gnutls_strerror(err));
			goto err;
		}
check_again:
		err = gnutls_pkcs12_bag_get_count(bag);
		if (err < 0) {
			ntfs_log_error("Failed to obtain Bag count: %s\n",
					gnutls_strerror(err));
			goto err;
		}
		err = gnutls_pkcs12_bag_get_type(bag, 0);
		if (err < 0) {
			ntfs_log_error("Failed to determine Bag type: %s\n",
					gnutls_strerror(err));
			goto err;
		}
		flags = 0;
		switch (err) {
		case GNUTLS_BAG_PKCS8_KEY:
			flags = GNUTLS_PKCS_PLAIN;
		case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
			err = gnutls_pkcs12_bag_get_data(bag, 0, &dkey);
			if (err < 0) {
				ntfs_log_error("Failed to obtain Bag data: "
						"%s\n", gnutls_strerror(err));
				goto err;
			}
			err = gnutls_x509_privkey_init(&pkey);
			if (err) {
				ntfs_log_error("Failed to initialized "
						"private key structure: %s\n",
						gnutls_strerror(err));
				goto err;
			}
			/* Decrypt the private key into GNU TLS format. */
			err = gnutls_x509_privkey_import_pkcs8(pkey, &dkey,
					GNUTLS_X509_FMT_DER, password, flags);
			if (err) {
				ntfs_log_error("Failed to convert private "
						"key from DER to GNU TLS "
						"format: %s\n",
						gnutls_strerror(err));
				goto err;
			}
#if 0
			/*
			 * Export the key again, but unencrypted, and output it
			 * to stderr.  Note the output has an RSA header so to
			 * compare to openssl pkcs12 -nodes -in myfile.pfx
			 * output need to ignore the part of the key between
			 * the first "MII..." up to the second "MII...".  The
			 * actual RSA private key begins at the second "MII..."
			 * and in my testing at least was identical to openssl
			 * output and was also identical both on big and little
			 * endian so gnutls should be endianness safe.
			 */
			char *buf = malloc(8192);
			size_t bufsize = 8192;
			err = gnutls_x509_privkey_export_pkcs8(pkey,
				GNUTLS_X509_FMT_PEM, "", GNUTLS_PKCS_PLAIN, buf,
				&bufsize);
			if (err) {
				ntfs_log_error("eek1\n");
				exit(1);
			}
			ntfs_log_error("%s\n", buf);
			free(buf);
#endif
			/* Convert the private key to our internal format. */
			rsa_key = ntfs_rsa_private_key_import_from_gnutls(pkey);
			if (!rsa_key)
				goto err;
			break;
		case GNUTLS_BAG_ENCRYPTED:
			err = gnutls_pkcs12_bag_decrypt(bag, password);
			if (err) {
				ntfs_log_error("Failed to decrypt Bag: %s\n",
						gnutls_strerror(err));
				goto err;
			}
			goto check_again;
		case GNUTLS_BAG_CERTIFICATE:
			err = gnutls_pkcs12_bag_get_data(bag, 0, &dkey);
			if (err < 0) {
				ntfs_log_error("Failed to obtain Bag data: "
						"%s\n", gnutls_strerror(err));
				goto err;
			}
			err = gnutls_x509_crt_init(&crt);
			if (err) {
				ntfs_log_error("Failed to initialize "
						"certificate structure: %s\n",
						gnutls_strerror(err));
				goto err;
			}
			err = gnutls_x509_crt_import(crt, &dkey,
					GNUTLS_X509_FMT_DER);
			if (err) {
				ntfs_log_error("Failed to convert certificate "
						"from DER to GNU TLS format: "
						"%s\n", gnutls_strerror(err));
				goto err;
			}
			oid_index = 0;
				/*
				 * Search in the key purposes for an EFS
				 * encryption purpose or an EFS recovery
				 * purpose, and use the first one found.
				 */
			do {
				purpose_oid_size = sizeof(purpose_oid);
				err = gnutls_x509_crt_get_key_purpose_oid(crt,
					oid_index,
					purpose_oid, &purpose_oid_size, NULL);
				if (!err) {
					purpose_oid[purpose_oid_size - 1]
							= '\0';
					if (!strcmp(purpose_oid,
						NTFS_EFS_CERT_PURPOSE_OID_DRF))
					*df_type = DF_TYPE_DRF;
					else if (!strcmp(purpose_oid,
						NTFS_EFS_CERT_PURPOSE_OID_DDF))
						*df_type = DF_TYPE_DDF;
					else
						oid_index++;
				}
			} while (!err && (*df_type == DF_TYPE_UNKNOWN));
			if (*df_type == DF_TYPE_UNKNOWN) {
				/* End of list reached ? */
				if (err
				    == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
					ntfs_log_error("Key does not have an "
						"EFS purpose OID\n");
				else
					ntfs_log_error("Failed to get a key "
							"purpose OID : %s ",
							gnutls_strerror(err));
				goto err;
			}
			/* Return the thumbprint to the caller. */
			err = gnutls_x509_crt_get_fingerprint(crt,
					GNUTLS_DIG_SHA1, thumbprint, &tp_size);
			if (err) {
				ntfs_log_error("Failed to get thumbprint: "
						"%s\n", gnutls_strerror(err));
				goto err;
			}
			if (tp_size != NTFS_SHA1_THUMBPRINT_SIZE) {
				ntfs_log_error("Invalid thumbprint size %zd.  "
						"Should be %d.\n", tp_size,
						thumbprint_size);
				err = EINVAL;
				goto err;
			}
			have_thumbprint = TRUE;
			gnutls_x509_crt_deinit(crt);
			crt = NULL;
			break;
		default:
			/* We do not care about other types. */
			break;
		}
		gnutls_pkcs12_bag_deinit(bag);
	}
err:
	if (rsa_key && (err || *df_type == DF_TYPE_UNKNOWN ||
			!have_thumbprint)) {
		if (!err)
			ntfs_log_error("Key type or thumbprint not found, "
					"aborting.\n");
		ntfs_rsa_private_key_release(rsa_key);
		rsa_key = NULL;
	}
	if (crt)
		gnutls_x509_crt_deinit(crt);
	if (pkey)
		gnutls_x509_privkey_deinit(pkey);
	if (bag)
		gnutls_pkcs12_bag_deinit(bag);
	if (pkcs12)
		gnutls_pkcs12_deinit(pkcs12);
	return rsa_key;
}
void
doit (void)
{
  int exit_val = 0;
  size_t i;
  int ret;

  /* The overloading of time() seems to work in linux (ELF?)
   * systems only. Disable it on windows.
   */
#ifdef _WIN32
  exit(77);
#endif

  ret = gnutls_global_init ();
  if (ret != 0)
    {
      fail ("%d: %s\n", ret, gnutls_strerror (ret));
      exit (EXIT_FAILURE);
    }

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

  for (i = 0; chains[i].chain; i++)
    {
      unsigned int verify_status;
      gnutls_x509_crt_t certs[4];
      gnutls_x509_crt_t ca;
      gnutls_datum_t tmp;
      size_t j;

      if (debug)
        printf ("Chain '%s' (%d)...\n", chains[i].name, (int) i);

      for (j = 0; chains[i].chain[j]; j++)
        {
          if (debug > 2)
            printf ("\tAdding certificate %d...", (int) j);

          ret = gnutls_x509_crt_init (&certs[j]);
          if (ret < 0)
            error (EXIT_FAILURE, 0, "gnutls_x509_crt_init[%d,%d]: %s",
                   (int) i, (int) j, gnutls_strerror (ret));

          tmp.data = (char *) chains[i].chain[j];
          tmp.size = strlen (chains[i].chain[j]);

          ret = gnutls_x509_crt_import (certs[j], &tmp, GNUTLS_X509_FMT_PEM);
          if (debug > 2)
            printf ("done\n");
          if (ret < 0)
            error (EXIT_FAILURE, 0, "gnutls_x509_crt_import[%d,%d]: %s",
                   (int) i, (int) j, gnutls_strerror (ret));

          gnutls_x509_crt_print (certs[j], GNUTLS_CRT_PRINT_ONELINE, &tmp);
          if (debug)
            printf ("\tCertificate %d: %.*s\n", (int) j, tmp.size, tmp.data);
          gnutls_free (tmp.data);
        }

      if (debug > 2)
        printf ("\tAdding CA certificate...");

      ret = gnutls_x509_crt_init (&ca);
      if (ret < 0)
        error (EXIT_FAILURE, 0, "gnutls_x509_crt_init: %s",
               gnutls_strerror (ret));

      tmp.data = (char *) *chains[i].ca;
      tmp.size = strlen (*chains[i].ca);

      ret = gnutls_x509_crt_import (ca, &tmp, GNUTLS_X509_FMT_PEM);
      if (ret < 0)
        error (EXIT_FAILURE, 0, "gnutls_x509_crt_import: %s",
               gnutls_strerror (ret));

      if (debug > 2)
        printf ("done\n");

      gnutls_x509_crt_print (ca, GNUTLS_CRT_PRINT_ONELINE, &tmp);
      if (debug)
        printf ("\tCA Certificate: %.*s\n", tmp.size, tmp.data);
      gnutls_free (tmp.data);

      if (debug)
        printf ("\tVerifying...");

      ret = gnutls_x509_crt_list_verify (certs, j,
                                         &ca, 1, NULL, 0,
                                         chains[i].verify_flags,
                                         &verify_status);
      if (ret < 0)
        error (EXIT_FAILURE, 0, "gnutls_x509_crt_list_verify[%d,%d]: %s",
               (int) i, (int) j, gnutls_strerror (ret));

      if (verify_status != chains[i].expected_verify_result)
        {
          fail ("chain[%s]: verify_status: %d expected: %d\n", chains[i].name,
                verify_status, chains[i].expected_verify_result);

#if 0
          j = 0;
          do
            {
              fprintf (stderr, "%s\n", chains[i].chain[j]);
            }
          while (chains[i].chain[++j] != NULL);
#endif

          if (!debug)
            exit (1);
        }
      else if (debug)
        printf ("done\n");
      if (debug)
        printf ("\tCleanup...");

      gnutls_x509_crt_deinit (ca);
      for (j = 0; chains[i].chain[j]; j++)
        gnutls_x509_crt_deinit (certs[j]);

      if (debug)
        printf ("done\n\n\n");
    }

  gnutls_global_deinit ();

  if (debug)
    printf ("Exit status...%d\n", exit_val);

  exit (exit_val);
}
int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn,
                           const u8 *in_data, size_t in_len,
                           u8 *out_data, size_t out_len)
{
        ssize_t res;

        if (conn->pull_buf) {
                wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
                           "pull_buf", __func__,
                           (unsigned long) conn->pull_buf_len);
                os_free(conn->pull_buf);
        }
        conn->pull_buf = os_malloc(in_len);
        if (conn->pull_buf == NULL)
                return -1;
        os_memcpy(conn->pull_buf, in_data, in_len);
        conn->pull_buf_offset = conn->pull_buf;
        conn->pull_buf_len = in_len;

#ifdef GNUTLS_IA
        if (conn->tls_ia) {
                res = gnutls_ia_recv(conn->session, (char *) out_data,
                                     out_len);
                if (out_len >= 12 &&
                    (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED ||
                     res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED)) {
                        int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED;
                        wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished",
                                   __func__, final ? "Final" : "Intermediate");

                        res = gnutls_ia_permute_inner_secret(
                                conn->session, conn->session_keys_len,
                                (char *) conn->session_keys);
                        if (conn->session_keys) {
                                os_memset(conn->session_keys, 0,
                                          conn->session_keys_len);
                                os_free(conn->session_keys);
                        }
                        conn->session_keys = NULL;
                        conn->session_keys_len = 0;
                        if (res) {
                                wpa_printf(MSG_DEBUG, "%s: Failed to permute "
                                           "inner secret: %s",
                                           __func__, gnutls_strerror(res));
                                return -1;
                        }

                        res = gnutls_ia_verify_endphase(conn->session,
                                                        (char *) out_data);
                        if (res == 0) {
                                wpa_printf(MSG_DEBUG, "%s: Correct endphase "
                                           "checksum", __func__);
                        } else {
                                wpa_printf(MSG_INFO, "%s: Endphase "
                                           "verification failed: %s",
                                           __func__, gnutls_strerror(res));
                                return -1;
                        }

                        if (final)
                                conn->final_phase_finished = 1;

                        return 0;
                }
Exemple #4
0
void doit(void)
{
#ifdef ENABLE_NON_SUITEB_CURVES
	const char *filename, *password = "******";
	gnutls_pkcs12_t pkcs12;
	gnutls_datum_t data;
	gnutls_x509_crt_t *chain, *extras;
	unsigned int chain_size = 0, extras_size = 0, i;
	gnutls_x509_privkey_t pkey;
	int ret;

	ret = global_init();
	if (ret < 0)
		fail("global_init failed %d\n", ret);

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

	ret = gnutls_pkcs12_init(&pkcs12);
	if (ret < 0)
		fail("initialization failed: %s\n", gnutls_strerror(ret));

	filename = getenv("PKCS12_MANY_CERTS_FILE");

	if (!filename)
		filename = "pkcs12-decode/pkcs12_5certs.p12";

	if (debug)
		success
		    ("Reading PKCS#12 blob from `%s' using password `%s'.\n",
		     filename, password);

	ret = gnutls_load_file(filename, &data);
	if (ret < 0)
		fail("cannot open file");

	ret = gnutls_pkcs12_import(pkcs12, &data, GNUTLS_X509_FMT_DER, 0);
	if (ret < 0)
		fail("pkcs12_import failed %d: %s\n", ret,
		     gnutls_strerror(ret));

	if (debug)
		success("Read file OK\n");

	ret =
	    gnutls_pkcs12_simple_parse(pkcs12, password, &pkey, &chain,
				       &chain_size, &extras, &extras_size,
				       NULL, 0);
	if (ret < 0)
		fail("pkcs12_simple_parse failed %d: %s\n", ret,
		     gnutls_strerror(ret));

	if (chain_size != 1)
		fail("chain size (%u) should have been 1\n", chain_size);

	if (extras_size != 4)
		fail("extras size (%u) should have been 4\n", extras_size);

	if (debug) {
		char dn[512];
		size_t dn_size;

		dn_size = sizeof(dn);
		ret = gnutls_x509_crt_get_dn(chain[0], dn, &dn_size);
		if (ret < 0)
			fail("crt_get_dn failed %d: %s\n", ret,
			     gnutls_strerror(ret));

		success("dn: %s\n", dn);

		dn_size = sizeof(dn);
		ret =
		    gnutls_x509_crt_get_issuer_dn(chain[0], dn, &dn_size);
		if (ret < 0)
			fail("crt_get_dn failed %d: %s\n", ret,
			     gnutls_strerror(ret));

		success("issuer dn: %s\n", dn);
	}

	gnutls_pkcs12_deinit(pkcs12);
	gnutls_x509_privkey_deinit(pkey);

	for (i = 0; i < chain_size; i++)
		gnutls_x509_crt_deinit(chain[i]);
	gnutls_free(chain);

	for (i = 0; i < extras_size; i++)
		gnutls_x509_crt_deinit(extras[i]);
	gnutls_free(extras);

	/* Try gnutls_x509_privkey_import2() */
	ret = gnutls_x509_privkey_init(&pkey);
	if (ret < 0)
		fail("gnutls_x509_privkey_init failed %d: %s\n", ret,
		     gnutls_strerror(ret));

	ret =
	    gnutls_x509_privkey_import2(pkey, &data, GNUTLS_X509_FMT_DER,
					password, 0);
	if (ret < 0)
		fail("gnutls_x509_privkey_import2 failed %d: %s\n", ret,
		     gnutls_strerror(ret));
	gnutls_x509_privkey_deinit(pkey);

	free(data.data);

	gnutls_global_deinit();
#else
	exit(77);
#endif
}
static
void server_initiated_handshake(void)
{
	/* 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;
	unsigned char buffer[64];
	int cret = GNUTLS_E_AGAIN;
	size_t transferred = 0;

	success("testing server initiated re-handshake\n");

	/* General init. */
	global_init();
	gnutls_global_set_log_function(tls_log_func);
	if (debug)
		gnutls_global_set_log_level(2);

	/* Init server */
	gnutls_certificate_allocate_credentials(&serverx509cred);
	gnutls_certificate_set_x509_key_mem(serverx509cred,
					    &server_cert, &server_key,
					    GNUTLS_X509_FMT_PEM);
	gnutls_init(&server, GNUTLS_SERVER);
	gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
				serverx509cred);
	gnutls_priority_set_direct(server, "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.3", NULL);
	gnutls_transport_set_push_function(server, server_push);
	gnutls_transport_set_pull_function(server, server_pull);
	gnutls_transport_set_ptr(server, server);

	/* Init client */
	gnutls_certificate_allocate_credentials(&clientx509cred);
	gnutls_init(&client, GNUTLS_CLIENT);
	gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
				clientx509cred);
	gnutls_priority_set_direct(client, "NORMAL:+VERS-TLS1.3", 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_protocol_get_version(client) != GNUTLS_TLS1_3)
		fail("TLS1.3 was not negotiated\n");

	sret = gnutls_rehandshake(server);
	if (debug) {
		tls_log_func(0, "gnutls_rehandshake (server)...\n");
		tls_log_func(0, gnutls_strerror(sret));
		tls_log_func(0, "\n");
	}

	{
		ssize_t n;
		char b[1];
		n = gnutls_record_recv(client, b, 1);
		/* in TLS1.2 we get REHANDSHAKE error, here nothing */
		if (n != GNUTLS_E_AGAIN) {
			fail("error msg: %s\n", gnutls_strerror(n));
		}
	}

	TRANSFER(client, server, "xxxx", 4, buffer, sizeof(buffer));

	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();

	reset_buffers();
}
Exemple #6
0
static void server(int fd, const char *prio, unsigned etm)
{
	int ret;
	char buffer[MAX_BUF + 1];
	gnutls_session_t session;
	gnutls_anon_server_credentials_t anoncred;
	gnutls_certificate_credentials_t x509_cred;
	unsigned to_send = sizeof(buffer)/4;

	/* this must be called once in the program
	 */
	global_init();
	memset(buffer, 0, sizeof(buffer));

	if (debug) {
		gnutls_global_set_log_function(server_log_func);
		gnutls_global_set_log_level(4711);
	}

	gnutls_certificate_allocate_credentials(&x509_cred);
	gnutls_certificate_set_x509_key_mem(x509_cred, &server_cert,
					    &server_key,
					    GNUTLS_X509_FMT_PEM);

	gnutls_anon_allocate_server_credentials(&anoncred);

	gnutls_init(&session, GNUTLS_SERVER);

	/* avoid calling all the priority functions, since the defaults
	 * are adequate.
	 */
	gnutls_priority_set_direct(session, prio, NULL);

	gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);
	gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);

	gnutls_transport_set_int(session, fd);

	do {
		ret = gnutls_handshake(session);
	} while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
	if (ret < 0) {
		close(fd);
		gnutls_deinit(session);
		fail("server: Handshake has failed (%s)\n\n",
		     gnutls_strerror(ret));
		terminate();
	}

	if (etm != 0 && gnutls_session_etm_status(session) == 0) {
		fail("server: EtM was not negotiated with %s!\n", prio);
		exit(1);
	} else if (etm == 0 && gnutls_session_etm_status(session) != 0) {
		fail("server: EtM was negotiated with %s!\n", prio);
		exit(1);
	}

	if (debug)
		success("server: Handshake was completed\n");

	if (debug)
		success("server: TLS version is: %s\n",
			gnutls_protocol_get_name
			(gnutls_protocol_get_version(session)));

	do {
		do {
			ret =
			    gnutls_record_send(session, buffer,
					       sizeof(buffer));
		} while (ret == GNUTLS_E_AGAIN
			 || ret == GNUTLS_E_INTERRUPTED);

		if (ret < 0) {
			fail("Error sending %d byte packet: %s\n", to_send,
			     gnutls_strerror(ret));
			terminate();
		}
		to_send++;
	}
	while (to_send < 64);

	to_send = -1;
	/* do not wait for the peer to close the connection.
	 */
	gnutls_bye(session, GNUTLS_SHUT_WR);

	close(fd);
	gnutls_deinit(session);

	gnutls_anon_free_server_credentials(anoncred);
	gnutls_certificate_free_credentials(x509_cred);

	gnutls_global_deinit();

	if (debug)
		success("server: finished\n");
}
static void client(int fd)
{
	int ret;
	char buffer[MAX_BUF + 1];
	gnutls_anon_client_credentials_t anoncred;
	gnutls_session_t session;
	/* Need to enable anonymous KX specifically. */

	global_init();

	if (debug) {
		gnutls_global_set_log_function(client_log_func);
		gnutls_global_set_log_level(4711);
	}

	gnutls_anon_allocate_client_credentials(&anoncred);

	/* Initialize TLS session
	 */
	gnutls_init(&session, GNUTLS_CLIENT | GNUTLS_DATAGRAM);
	gnutls_dtls_set_mtu(session, 1500);
	gnutls_handshake_set_timeout(session, 20 * 1000);

	/* Use default priorities */
	gnutls_priority_set_direct(session,
				   "NONE:+VERS-DTLS-ALL:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL",
				   NULL);

	/* put the anonymous credentials to the current session
	 */
	gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);

	gnutls_transport_set_int(session, fd);
	gnutls_transport_set_push_function(session, push);

	/* Perform the TLS handshake
	 */
	do {
		ret = gnutls_handshake(session);
	}
	while (ret < 0 && gnutls_error_is_fatal(ret) == 0);

	if (ret < 0) {
		fail("client: Handshake failed\n");
		gnutls_perror(ret);
		exit(1);
	} else {
		if (debug)
			success("client: Handshake was completed\n");
	}

	if (debug)
		success("client: TLS version is: %s\n",
			gnutls_protocol_get_name
			(gnutls_protocol_get_version(session)));

	do {
		ret = gnutls_record_recv(session, buffer, MAX_BUF);
	} while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);

	if (ret == 0) {
		if (debug)
			success
			    ("client: Peer has closed the TLS connection\n");
		goto end;
	} else if (ret < 0) {
		fail("client: Error: %s\n", gnutls_strerror(ret));
		exit(1);
	}

	gnutls_bye(session, GNUTLS_SHUT_WR);

      end:

	close(fd);

	gnutls_deinit(session);

	gnutls_anon_free_client_credentials(anoncred);

	gnutls_global_deinit();
}
Exemple #8
0
static void
cipher_bench (int algo, int size)
{
  int ret;
  gnutls_cipher_hd_t ctx;
  void *_key, *_iv;
  gnutls_datum_t key, iv;
  struct timespec start, stop;
  double secs;
  double data_size = 0;
  double dspeed, ddata;
  int blocksize = gnutls_cipher_get_block_size (algo);
  int keysize = gnutls_cipher_get_key_size (algo);
  char metric[16];

  _key = malloc (keysize);
  if (_key == NULL)
    return;
  memset (_key, 0xf0, keysize);

  _iv = malloc (blocksize);
  if (_iv == NULL)
    return;
  memset (_iv, 0xf0, blocksize);

  iv.data = _iv;
  iv.size = blocksize;

  key.data = _key;
  key.size = keysize;

  printf ("Checking %s (%dkb payload)... ", gnutls_cipher_get_name (algo),
          size);
  fflush (stdout);

  must_finish = 0;
  alarm (5);

  gettime (&start);

  ret = gnutls_cipher_init (&ctx, algo, &key, &iv);
  if (ret < 0)
    {
      fprintf (stderr, "error: %s\n", gnutls_strerror (ret));
      goto leave;
    }

  do
    {
      gnutls_cipher_encrypt (ctx, data, size * 1024);
      data_size += size * 1024;
    }
  while (must_finish == 0);

  gnutls_cipher_deinit (ctx);

  gettime (&stop);

  secs = (stop.tv_sec * 1000 + stop.tv_nsec / (1000 * 1000) -
          (start.tv_sec * 1000 + start.tv_nsec / (1000 * 1000)));
  secs /= 1000;

  value2human (data_size, secs, &ddata, &dspeed, metric);
  printf ("Encrypted %.2f %s in %.2f secs: ", ddata, metric, secs);
  printf ("%.2f %s/sec\n", dspeed, metric);

leave:
  free (_key);
  free (_iv);

}
Exemple #9
0
void
doit (void)
{
  /* Server stuff. */
  gnutls_anon_server_credentials_t s_anoncred;
  const gnutls_datum_t p3 = { (char *) pkcs3, strlen (pkcs3) };
  static gnutls_dh_params_t dh_params;
  gnutls_session_t server;
  int sret = GNUTLS_E_AGAIN;
  /* Client stuff. */
  gnutls_anon_client_credentials_t c_anoncred;
  gnutls_session_t client;
  int n, cret = GNUTLS_E_AGAIN;
  /* Need to enable anonymous KX specifically. */
  const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };
  char buffer[MAX_BUF + 1];
  ssize_t ns;
  int ret;

  /* General init. */
  gnutls_global_init ();
  gnutls_global_set_log_function (tls_log_func);
  if (debug)
    gnutls_global_set_log_level (4711);

  /* Init server */
  gnutls_anon_allocate_server_credentials (&s_anoncred);
  gnutls_dh_params_init (&dh_params);
  gnutls_dh_params_import_pkcs3 (dh_params, &p3, GNUTLS_X509_FMT_PEM);
  gnutls_anon_set_server_dh_params (s_anoncred, dh_params);
  gnutls_init (&server, GNUTLS_SERVER);
  gnutls_set_default_priority (server);
  gnutls_kx_set_priority (server, kx_prio);
  gnutls_credentials_set (server, GNUTLS_CRD_ANON, s_anoncred);
  gnutls_dh_set_prime_bits (server, 1024);
  gnutls_transport_set_push_function (server, server_push);
  gnutls_transport_set_pull_function (server, server_pull);
  gnutls_session_set_finished_function (server, server_finished_callback);

  /* Init client */
  gnutls_anon_allocate_client_credentials (&c_anoncred);
  gnutls_init (&client, GNUTLS_CLIENT);
  gnutls_set_default_priority (client);
  gnutls_kx_set_priority (client, kx_prio);
  gnutls_credentials_set (client, GNUTLS_CRD_ANON, c_anoncred);
  gnutls_transport_set_push_function (client, client_push);
  gnutls_transport_set_pull_function (client, client_pull);
  gnutls_session_set_finished_function (client, client_finished_callback);

  do
    {
      if (cret == GNUTLS_E_AGAIN)
	{
	  if (debug)
	    success ("loop invoking client:\n");
	  cret = gnutls_handshake (client);
	  if (debug)
	    success ("client %d: %s\n", cret, gnutls_strerror (cret));
	}

      if (sret == GNUTLS_E_AGAIN)
	{
	  if (debug)
	    success ("loop invoking server:\n");
	  sret = gnutls_handshake (server);
	  if (debug)
	    success ("server %d: %s\n", sret, gnutls_strerror (sret));
	}
    }
  while (cret == GNUTLS_E_AGAIN || sret == GNUTLS_E_AGAIN);

  if (debug)
    success ("Handshake established\n");

  ns = gnutls_record_send (client, MSG, strlen (MSG));
  if (debug)
    success ("client: sent %d\n", (int) ns);

  ret = gnutls_record_recv (server, buffer, MAX_BUF);
  if (ret == 0)
    fail ("server: didn't receive any data\n");
  else if (ret < 0)
    fail ("server: error: %s\n", gnutls_strerror (ret));
  else if (debug)
    {
      printf ("server: received %d: ", ret);
      for (n = 0; n < ret; n++)
	fputc (buffer[n], stdout);
      fputs ("\n", stdout);
    }

  ns = gnutls_record_send (server, MSG, strlen (MSG));
  if (debug)
    success ("server: sent %d\n", (int) ns);

  ret = gnutls_record_recv (client, buffer, MAX_BUF);
  if (ret == 0)
    {
      fail ("client: Peer has closed the TLS connection\n");
    }
  else if (ret < 0)
    {
      fail ("client: Error: %s\n", gnutls_strerror (ret));
    }
  else if (debug)
    {
      printf ("client: received %d: ", ret);
      for (n = 0; n < ret; n++)
	fputc (buffer[n], stdout);
      fputs ("\n", stdout);
    }

  gnutls_bye (client, GNUTLS_SHUT_RDWR);
  gnutls_bye (server, GNUTLS_SHUT_RDWR);

  gnutls_deinit (client);
  gnutls_deinit (server);

  free (to_server);
  free (to_client);

  gnutls_anon_free_client_credentials (c_anoncred);
  gnutls_anon_free_server_credentials (s_anoncred);

  gnutls_dh_params_deinit (dh_params);

  gnutls_global_deinit ();
}
static int				/* O - 1 on success, 0 on failure */
make_certificate(cupsd_client_t *con)	/* I - Client connection */
{
  gnutls_x509_crt	crt;		/* Self-signed certificate */
  gnutls_x509_privkey	key;		/* Encryption key */
  cups_lang_t		*language;	/* Default language info */
  cups_file_t		*fp;		/* Key/cert file */
  unsigned char		buffer[8192];	/* Buffer for x509 data */
  size_t		bytes;		/* Number of bytes of data */
  unsigned char		serial[4];	/* Serial number buffer */
  time_t		curtime;	/* Current time */
  int			result;		/* Result of GNU TLS calls */


 /*
  * Create the encryption key...
  */

  cupsdLogMessage(CUPSD_LOG_INFO, "Generating SSL server key...");

  gnutls_x509_privkey_init(&key);
  gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 2048, 0);

 /*
  * Save it...
  */

  bytes = sizeof(buffer);

  if ((result = gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM,
                                           buffer, &bytes)) < 0)
  {
    cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to export SSL server key - %s",
                    gnutls_strerror(result));
    gnutls_x509_privkey_deinit(key);
    return (0);
  }
  else if ((fp = cupsFileOpen(ServerKey, "w")) != NULL)
  {
    cupsFileWrite(fp, (char *)buffer, bytes);
    cupsFileClose(fp);

    cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server key file \"%s\"...",
		    ServerKey);
  }
  else
  {
    cupsdLogMessage(CUPSD_LOG_ERROR,
                    "Unable to create SSL server key file \"%s\" - %s",
		    ServerKey, strerror(errno));
    gnutls_x509_privkey_deinit(key);
    return (0);
  }

 /*
  * Create the self-signed certificate...
  */

  cupsdLogMessage(CUPSD_LOG_INFO, "Generating self-signed SSL certificate...");

  language  = cupsLangDefault();
  curtime   = time(NULL);
  serial[0] = curtime >> 24;
  serial[1] = curtime >> 16;
  serial[2] = curtime >> 8;
  serial[3] = curtime;

  gnutls_x509_crt_init(&crt);
  if (strlen(language->language) == 5)
    gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0,
                                  language->language + 3, 2);
  else
    gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0,
                                  "US", 2);
  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COMMON_NAME, 0,
                                ServerName, strlen(ServerName));
  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATION_NAME, 0,
                                ServerName, strlen(ServerName));
  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME,
                                0, "Unknown", 7);
  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0,
                                "Unknown", 7);
  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_LOCALITY_NAME, 0,
                                "Unknown", 7);
  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_PKCS9_EMAIL, 0,
                                ServerAdmin, strlen(ServerAdmin));
  gnutls_x509_crt_set_key(crt, key);
  gnutls_x509_crt_set_serial(crt, serial, sizeof(serial));
  gnutls_x509_crt_set_activation_time(crt, curtime);
  gnutls_x509_crt_set_expiration_time(crt, curtime + 10 * 365 * 86400);
  gnutls_x509_crt_set_ca_status(crt, 0);
  gnutls_x509_crt_set_subject_alternative_name(crt, GNUTLS_SAN_DNSNAME,
                                               ServerName);
  gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_SERVER, 0);
  gnutls_x509_crt_set_key_usage(crt, GNUTLS_KEY_KEY_ENCIPHERMENT);
  gnutls_x509_crt_set_version(crt, 3);

  bytes = sizeof(buffer);
  if (gnutls_x509_crt_get_key_id(crt, 0, buffer, &bytes) >= 0)
    gnutls_x509_crt_set_subject_key_id(crt, buffer, bytes);

  gnutls_x509_crt_sign(crt, crt, key);

 /*
  * Save it...
  */

  bytes = sizeof(buffer);
  if ((result = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM,
                                       buffer, &bytes)) < 0)
    cupsdLogMessage(CUPSD_LOG_ERROR,
                    "Unable to export SSL server certificate - %s",
		    gnutls_strerror(result));
  else if ((fp = cupsFileOpen(ServerCertificate, "w")) != NULL)
  {
    cupsFileWrite(fp, (char *)buffer, bytes);
    cupsFileClose(fp);

    cupsdLogMessage(CUPSD_LOG_INFO,
                    "Created SSL server certificate file \"%s\"...",
		    ServerCertificate);
  }
  else
    cupsdLogMessage(CUPSD_LOG_ERROR,
                    "Unable to create SSL server certificate file \"%s\" - %s",
		    ServerCertificate, strerror(errno));

 /*
  * Cleanup...
  */

  gnutls_x509_crt_deinit(crt);
  gnutls_x509_privkey_deinit(key);

  return (1);
}
int					/* O - 1 on success, 0 on error */
cupsdStartTLS(cupsd_client_t *con)	/* I - Client connection */
{
  int		status;			/* Error code */
  gnutls_certificate_server_credentials *credentials;
					/* TLS credentials */


  cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Encrypting connection.",
                  con->http.fd);

 /*
  * Verify that we have a certificate...
  */

  if (access(ServerKey, 0) || access(ServerCertificate, 0))
  {
   /*
    * Nope, make a self-signed certificate...
    */

    if (!make_certificate(con))
      return (0);
  }

 /*
  * Create the SSL object and perform the SSL handshake...
  */

  credentials = (gnutls_certificate_server_credentials *)
                    malloc(sizeof(gnutls_certificate_server_credentials));
  if (credentials == NULL)
  {
    cupsdLogMessage(CUPSD_LOG_ERROR,
                    "Unable to encrypt connection from %s - %s",
                    con->http.hostname, strerror(errno));

    return (0);
  }

  gnutls_certificate_allocate_credentials(credentials);
  gnutls_certificate_set_x509_key_file(*credentials, ServerCertificate,
				       ServerKey, GNUTLS_X509_FMT_PEM);

  gnutls_init(&con->http.tls, GNUTLS_SERVER);
  gnutls_set_default_priority(con->http.tls);

  gnutls_credentials_set(con->http.tls, GNUTLS_CRD_CERTIFICATE, *credentials);
  gnutls_transport_set_ptr(con->http.tls, (gnutls_transport_ptr)HTTP(con));
  gnutls_transport_set_pull_function(con->http.tls, _httpReadGNUTLS);
  gnutls_transport_set_push_function(con->http.tls, _httpWriteGNUTLS);

  while ((status = gnutls_handshake(con->http.tls)) != GNUTLS_E_SUCCESS)
  {
    if (gnutls_error_is_fatal(status))
    {
      cupsdLogMessage(CUPSD_LOG_ERROR,
                      "Unable to encrypt connection from %s - %s",
                      con->http.hostname, gnutls_strerror(status));

      gnutls_deinit(con->http.tls);
      gnutls_certificate_free_credentials(*credentials);
      con->http.tls = NULL;
      free(credentials);
      return (0);
    }
  }

  cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.",
                  con->http.hostname);

  con->http.tls_credentials = credentials;
  return (1);
}
Exemple #12
0
TDSRET
tds_ssl_init(TDSSOCKET *tds)
{
	gnutls_session_t session;
	gnutls_certificate_credentials_t xcred;
	int ret;
	const char *tls_msg;

	xcred = NULL;
	session = NULL;	
	tls_msg = "initializing tls";

	if (!tls_initialized) {
		ret = 0;
		tds_mutex_lock(&tls_mutex);
		if (!tls_initialized) {
			tds_gcry_init();
			ret = gnutls_global_init();
			if (ret == 0)
				tls_initialized = 1;
		}
		tds_mutex_unlock(&tls_mutex);
		if (ret != 0)
			goto cleanup;
	}

	if (tds_write_dump && tls_initialized < 2) {
		gnutls_global_set_log_level(11);
		gnutls_global_set_log_function(tds_tls_log);
		tls_initialized = 2;
	}

	tls_msg = "allocating credentials";
	ret = gnutls_certificate_allocate_credentials(&xcred);
	if (ret != 0)
		goto cleanup;

	if (!tds_dstr_isempty(&tds->login->cafile)) {
		tls_msg = "loading CA file";
		if (strcasecmp(tds_dstr_cstr(&tds->login->cafile), "system") == 0)
			ret = gnutls_certificate_set_x509_system_trust(xcred);
		else
			ret = gnutls_certificate_set_x509_trust_file(xcred, tds_dstr_cstr(&tds->login->cafile), GNUTLS_X509_FMT_PEM);
		if (ret <= 0)
			goto cleanup;
		if (!tds_dstr_isempty(&tds->login->crlfile)) {
			tls_msg = "loading CRL file";
			ret = gnutls_certificate_set_x509_crl_file(xcred, tds_dstr_cstr(&tds->login->crlfile), GNUTLS_X509_FMT_PEM);
			if (ret <= 0)
				goto cleanup;
		}
		gnutls_certificate_set_verify_function(xcred, tds_verify_certificate);
	}

	/* Initialize TLS session */
	tls_msg = "initializing session";
	ret = gnutls_init(&session, GNUTLS_CLIENT);
	if (ret != 0)
		goto cleanup;

	gnutls_transport_set_ptr(session, tds);
	gnutls_transport_set_pull_function(session, tds_pull_func_login);
	gnutls_transport_set_push_function(session, tds_push_func_login);

	/* NOTE: there functions return int however they cannot fail */

	/* use default priorities... */
	gnutls_set_default_priority(session);

	/* ... but overwrite some */
	ret = gnutls_priority_set_direct (session, "NORMAL:%COMPAT:-VERS-SSL3.0", NULL);
	if (ret != 0)
		goto cleanup;

	/* mssql does not like padding too much */
#ifdef HAVE_GNUTLS_RECORD_DISABLE_PADDING
	gnutls_record_disable_padding(session);
#endif

	/* put the anonymous credentials to the current session */
	tls_msg = "setting credential";
	ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);
	if (ret != 0)
		goto cleanup;

	/* Perform the TLS handshake */
	tls_msg = "handshake";
	ret = gnutls_handshake (session);
	if (ret != 0)
		goto cleanup;

	tdsdump_log(TDS_DBG_INFO1, "handshake succeeded!!\n");

	gnutls_transport_set_ptr(session, tds->conn);
	gnutls_transport_set_pull_function(session, tds_pull_func);
	gnutls_transport_set_push_function(session, tds_push_func);

	tds->conn->tls_session = session;
	tds->conn->tls_credentials = xcred;

	return TDS_SUCCESS;

cleanup:
	if (session)
		gnutls_deinit(session);
	if (xcred)
		gnutls_certificate_free_credentials(xcred);
	tdsdump_log(TDS_DBG_ERROR, "%s failed: %s\n", tls_msg, gnutls_strerror (ret));
	return TDS_FAIL;
}
Exemple #13
0
static int
tds_verify_certificate(gnutls_session_t session)
{
	unsigned int status;
	int ret;
	TDSSOCKET *tds = (TDSSOCKET *) gnutls_transport_get_ptr(session);

#ifdef ENABLE_DEVELOPING
	unsigned int list_size;
	const gnutls_datum_t *cert_list;
#endif

	if (!tds->login)
		return GNUTLS_E_CERTIFICATE_ERROR;

	ret = gnutls_certificate_verify_peers2(session, &status);
	if (ret < 0) {
		tdsdump_log(TDS_DBG_ERROR, "Error verifying certificate: %s\n", gnutls_strerror(ret));
		return GNUTLS_E_CERTIFICATE_ERROR;
	}

#ifdef ENABLE_DEVELOPING
	cert_list = gnutls_certificate_get_peers(session, &list_size);
	if (cert_list) {
		gnutls_x509_crt_t cert;
		gnutls_datum_t cinfo;
		char buf[8192];
		size_t size;

		gnutls_x509_crt_init(&cert);

		gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);

		/* This is the preferred way of printing short information about
		 * a certificate. */
		size = sizeof(buf);
		ret = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_PEM, buf, &size);
		if (ret == 0) {
			FILE *f = fopen("cert.dat", "wb");
			if (f) {
				fwrite(buf, size, 1, f);
				fclose(f);
			}
		}

		ret = gnutls_x509_crt_print(cert, GNUTLS_CRT_PRINT_ONELINE, &cinfo);
		if (ret == 0) {
			tdsdump_log(TDS_DBG_INFO1, "Certificate info: %s\n", cinfo.data);
			gnutls_free(cinfo.data);
		}

		gnutls_x509_crt_deinit(cert);
	}
#endif

	/* Certificate is not trusted */
	if (status != 0) {
		tdsdump_log(TDS_DBG_ERROR, "Certificate status: %u\n", status);
		return GNUTLS_E_CERTIFICATE_ERROR;
	}

	/* check hostname */
	if (tds->login->check_ssl_hostname) {
		const gnutls_datum_t *cert_list;
		unsigned int list_size;
		gnutls_x509_crt_t cert;

		cert_list = gnutls_certificate_get_peers(session, &list_size);
		if (!cert_list) {
			tdsdump_log(TDS_DBG_ERROR, "Error getting TLS session peers\n");
			return GNUTLS_E_CERTIFICATE_ERROR;
		}
		gnutls_x509_crt_init(&cert);
		gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
		ret = gnutls_x509_crt_check_hostname(cert, tds_dstr_cstr(&tds->login->server_host_name));
		gnutls_x509_crt_deinit(cert);
		if (!ret) {
			tdsdump_log(TDS_DBG_ERROR, "Certificate hostname does not match\n");
			return GNUTLS_E_CERTIFICATE_ERROR;
		}
	}

	/* notify gnutls to continue handshake normally */
	return 0;
}
Exemple #14
0
int ssl_open(http_t *client, char *msg)
{
	int ret;
	char buf[256];
	size_t len;
	const char *sn, *err;
	const gnutls_datum_t *cert_list;
	unsigned int cert_list_size = 0;
	gnutls_x509_crt_t cert;

	if (!client->ssl_enabled)
		return tcp_init(&client->tcp, msg);

	/* Initialize TLS session */
	logit(LOG_INFO, "%s, initiating HTTPS ...", msg);
	gnutls_init(&client->ssl, GNUTLS_CLIENT);

	/* SSL SNI support: tell the servername we want to speak to */
	http_get_remote_name(client, &sn);
	gnutls_session_set_ptr(client->ssl, (void *)sn);
	if (gnutls_server_name_set(client->ssl, GNUTLS_NAME_DNS, sn, strlen(sn)))
		return RC_HTTPS_SNI_ERROR;

	/* Use default priorities */
	ret = gnutls_priority_set_direct(client->ssl, "NORMAL", &err);
	if (ret < 0) {
		if (ret == GNUTLS_E_INVALID_REQUEST)
			logit(LOG_ERR, "Syntax error at: %s", err);

		return RC_HTTPS_INVALID_REQUEST;
	}

	/* put the x509 credentials to the current session */
	gnutls_credentials_set(client->ssl, GNUTLS_CRD_CERTIFICATE, xcred);

	/* connect to the peer */
	tcp_set_port(&client->tcp, HTTPS_DEFAULT_PORT);
	DO(tcp_init(&client->tcp, msg));

	/* Forward TCP socket to GnuTLS, the set_int() API is perhaps too new still ... since 3.1.9 */
//	gnutls_transport_set_int(client->ssl, client->tcp.ip.socket);
	gnutls_transport_set_ptr(client->ssl, (gnutls_transport_ptr_t)(intptr_t)client->tcp.ip.socket);

	/* Perform the TLS handshake, ignore non-fatal errors. */
	do {
		ret = gnutls_handshake(client->ssl);
	}
	while (ret != 0 && !gnutls_error_is_fatal(ret));

	if (gnutls_error_is_fatal(ret)) {
		logit(LOG_ERR, "SSL handshake with %s failed: %s", sn, gnutls_strerror(ret));
		return RC_HTTPS_FAILED_CONNECT;
	}

	ssl_get_info(client);

	/* Get server's certificate (note: beware of dynamic allocation) - opt */
	cert_list = gnutls_certificate_get_peers(client->ssl, &cert_list_size);
	if (cert_list_size > 0) {
		if (gnutls_x509_crt_init(&cert))
			return RC_HTTPS_FAILED_GETTING_CERT;

		gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);

		len = sizeof(buf);
		gnutls_x509_crt_get_dn(cert, buf, &len);
		logit(LOG_INFO, "SSL server cert subject: %s", buf);

		len = sizeof(buf);
		gnutls_x509_crt_get_issuer_dn(cert, buf, &len);
		logit(LOG_INFO, "SSL server cert issuer: %s", buf);

		gnutls_x509_crt_deinit(cert);
	}

	return 0;
}
Exemple #15
0
static void test_ciphersuite_kx(const char *cipher_prio, unsigned pk)
{
	/* Server stuff. */
	gnutls_anon_server_credentials_t s_anoncred;
	gnutls_session_t server;
	int sret, cret;
	const char *str;
	char *suite = NULL;
	/* Client stuff. */
	gnutls_anon_client_credentials_t c_anoncred;
	gnutls_certificate_credentials_t c_certcred, s_certcred;
	gnutls_session_t client;
	/* Need to enable anonymous KX specifically. */
	int ret;
	struct benchmark_st st;
	struct timespec tr_start, tr_stop;
	double avg, sstddev;
	gnutls_priority_t priority_cache;

	total_diffs_size = 0;

	/* Init server */
	gnutls_certificate_allocate_credentials(&s_certcred);
	gnutls_anon_allocate_server_credentials(&s_anoncred);

	ret = 0;
	if (pk == GNUTLS_PK_RSA_PSS)
		ret = gnutls_certificate_set_x509_key_mem(s_certcred, &server_rsa_pss_cert,
						    &server_key,
						    GNUTLS_X509_FMT_PEM);
	else if (pk == GNUTLS_PK_RSA)
		ret = gnutls_certificate_set_x509_key_mem(s_certcred, &server_cert,
						    &server_key,
						    GNUTLS_X509_FMT_PEM);
	if (ret < 0) {
		fprintf(stderr, "Error in %d: %s\n", __LINE__,
			gnutls_strerror(ret));
		exit(1);
	}

	ret = 0;
	if (pk == GNUTLS_PK_ECDSA)
		ret = gnutls_certificate_set_x509_key_mem(s_certcred, &server_ecc_cert,
						    &server_ecc_key,
						    GNUTLS_X509_FMT_PEM);
	else if (pk == GNUTLS_PK_EDDSA_ED25519)
		ret = gnutls_certificate_set_x509_key_mem(s_certcred, &server_ed25519_cert,
						    &server_ed25519_key,
						    GNUTLS_X509_FMT_PEM);
	if (ret < 0) {
		fprintf(stderr, "Error in %d: %s\n", __LINE__,
			gnutls_strerror(ret));
		exit(1);
	}

	/* Init client */
	gnutls_anon_allocate_client_credentials(&c_anoncred);
	gnutls_certificate_allocate_credentials(&c_certcred);

	start_benchmark(&st);

	ret = gnutls_priority_init(&priority_cache, cipher_prio, &str);
	if (ret < 0) {
		fprintf(stderr, "Error in %s\n", str);
		exit(1);
	}

	do {

		gnutls_init(&server, GNUTLS_SERVER);
		ret =
		    gnutls_priority_set(server, priority_cache);
		if (ret < 0) {
			fprintf(stderr, "Error in setting priority: %s\n", gnutls_strerror(ret));
			exit(1);
		}
		gnutls_credentials_set(server, GNUTLS_CRD_ANON,
				       s_anoncred);
		gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
				       s_certcred);
		gnutls_transport_set_push_function(server, server_push);
		gnutls_transport_set_pull_function(server, server_pull);
		gnutls_transport_set_ptr(server,
					 (gnutls_transport_ptr_t) server);
		reset_buffers();

		gnutls_init(&client, GNUTLS_CLIENT);

		ret =
		    gnutls_priority_set(client, priority_cache);
		if (ret < 0) {
			fprintf(stderr, "Error in setting priority: %s\n", gnutls_strerror(ret));
			exit(1);
		}
		gnutls_credentials_set(client, GNUTLS_CRD_ANON,
				       c_anoncred);
		gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
				       c_certcred);

		gnutls_transport_set_push_function(client, client_push);
		gnutls_transport_set_pull_function(client, client_pull);
		gnutls_transport_set_ptr(client,
					 (gnutls_transport_ptr_t) client);

		gettime(&tr_start);

		HANDSHAKE(client, server);

		gettime(&tr_stop);

		if (suite == NULL)
			suite =
			    gnutls_session_get_desc(server);

		gnutls_deinit(client);
		gnutls_deinit(server);

		total_diffs[total_diffs_size++] = timespec_sub_ms(&tr_stop, &tr_start);
		if (total_diffs_size > sizeof(total_diffs)/sizeof(total_diffs[0]))
			abort();

		st.size += 1;
	}
	while (benchmark_must_finish == 0);

	fprintf(stdout, "%38s  ", suite);
	gnutls_free(suite);
	stop_benchmark(&st, "transactions", 1);
	gnutls_priority_deinit(priority_cache);

	avg = calc_avg(total_diffs, total_diffs_size);
	sstddev = calc_sstdev(total_diffs, total_diffs_size, avg);

	printf("%32s %.2f ms, sample variance: %.2f)\n",
	       "(avg. handshake time:", avg, sstddev);

	gnutls_anon_free_client_credentials(c_anoncred);
	gnutls_anon_free_server_credentials(s_anoncred);
}
	void VerifyCertificate()
	{
		unsigned int certstatus;
		const gnutls_datum_t* cert_list;
		int ret;
		unsigned int cert_list_size;
		gnutls_x509_crt_t cert;
		char str[512];
		unsigned char digest[512];
		size_t digest_size = sizeof(digest);
		size_t name_size = sizeof(str);
		ssl_cert* certinfo = new ssl_cert;
		this->certificate = certinfo;

		/* This verification function uses the trusted CAs in the credentials
		 * structure. So you must have installed one or more CA certificates.
		 */
		ret = gnutls_certificate_verify_peers2(this->sess, &certstatus);

		if (ret < 0)
		{
			certinfo->error = std::string(gnutls_strerror(ret));
			return;
		}

		certinfo->invalid = (certstatus & GNUTLS_CERT_INVALID);
		certinfo->unknownsigner = (certstatus & GNUTLS_CERT_SIGNER_NOT_FOUND);
		certinfo->revoked = (certstatus & GNUTLS_CERT_REVOKED);
		certinfo->trusted = !(certstatus & GNUTLS_CERT_SIGNER_NOT_CA);

		/* Up to here the process is the same for X.509 certificates and
		 * OpenPGP keys. From now on X.509 certificates are assumed. This can
		 * be easily extended to work with openpgp keys as well.
		 */
		if (gnutls_certificate_type_get(this->sess) != GNUTLS_CRT_X509)
		{
			certinfo->error = "No X509 keys sent";
			return;
		}

		ret = gnutls_x509_crt_init(&cert);
		if (ret < 0)
		{
			certinfo->error = gnutls_strerror(ret);
			return;
		}

		cert_list_size = 0;
		cert_list = gnutls_certificate_get_peers(this->sess, &cert_list_size);
		if (cert_list == NULL)
		{
			certinfo->error = "No certificate was found";
			goto info_done_dealloc;
		}

		/* This is not a real world example, since we only check the first
		 * certificate in the given chain.
		 */

		ret = gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);
		if (ret < 0)
		{
			certinfo->error = gnutls_strerror(ret);
			goto info_done_dealloc;
		}

		if (gnutls_x509_crt_get_dn(cert, str, &name_size) == 0)
		{
			std::string& dn = certinfo->dn;
			dn = str;
			// Make sure there are no chars in the string that we consider invalid
			if (dn.find_first_of("\r\n") != std::string::npos)
				dn.clear();
		}

		name_size = sizeof(str);
		if (gnutls_x509_crt_get_issuer_dn(cert, str, &name_size) == 0)
		{
			std::string& issuer = certinfo->issuer;
			issuer = str;
			if (issuer.find_first_of("\r\n") != std::string::npos)
				issuer.clear();
		}

		if ((ret = gnutls_x509_crt_get_fingerprint(cert, profile->GetHash(), digest, &digest_size)) < 0)
		{
			certinfo->error = gnutls_strerror(ret);
		}
		else
		{
			certinfo->fingerprint = BinToHex(digest, digest_size);
		}

		/* Beware here we do not check for errors.
		 */
		if ((gnutls_x509_crt_get_expiration_time(cert) < ServerInstance->Time()) || (gnutls_x509_crt_get_activation_time(cert) > ServerInstance->Time()))
		{
			certinfo->error = "Not activated, or expired certificate";
		}

info_done_dealloc:
		gnutls_x509_crt_deinit(cert);
	}
Exemple #17
0
static void client(int fd, const char *prio, unsigned etm)
{
	int ret;
	char buffer[MAX_BUF + 1];
	gnutls_anon_client_credentials_t anoncred;
	gnutls_certificate_credentials_t x509_cred;
	gnutls_session_t session;
	/* Need to enable anonymous KX specifically. */

	global_init();

	if (debug) {
		gnutls_global_set_log_function(client_log_func);
		gnutls_global_set_log_level(7);
	}

	gnutls_anon_allocate_client_credentials(&anoncred);
	gnutls_certificate_allocate_credentials(&x509_cred);

	/* Initialize TLS session
	 */
	gnutls_init(&session, GNUTLS_CLIENT);

	/* Use default priorities */
	gnutls_priority_set_direct(session, prio, NULL);

	/* put the anonymous credentials to the current session
	 */
	gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);
	gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);

	gnutls_transport_set_int(session, fd);

	/* Perform the TLS handshake
	 */
	do {
		ret = gnutls_handshake(session);
	}
	while (ret < 0 && gnutls_error_is_fatal(ret) == 0);

	if (ret < 0) {
		fail("client: Handshake failed\n");
		gnutls_perror(ret);
		exit(1);
	} else {
		if (debug)
			success("client: Handshake was completed\n");
	}

	if (debug)
		success("client: TLS version is: %s\n",
			gnutls_protocol_get_name
			(gnutls_protocol_get_version(session)));

	if (etm != 0 && gnutls_session_etm_status(session) == 0) {
		fail("server: EtM was not negotiated with %s!\n", prio);
		exit(1);
	} else if (etm == 0 && gnutls_session_etm_status(session) != 0) {
		fail("server: EtM was negotiated with %s!\n", prio);
		exit(1);
	}

	do {
		do {
			ret = gnutls_record_recv(session, buffer, MAX_BUF);
		} while (ret == GNUTLS_E_AGAIN
			 || ret == GNUTLS_E_INTERRUPTED);
	} while (ret > 0);

	if (ret == 0) {
		if (debug)
			success
			    ("client: Peer has closed the TLS connection\n");
		goto end;
	} else if (ret < 0) {
		if (ret != 0) {
			fail("client: Error: %s\n", gnutls_strerror(ret));
			exit(1);
		}
	}

	gnutls_bye(session, GNUTLS_SHUT_WR);

      end:

	close(fd);

	gnutls_deinit(session);

	gnutls_anon_free_client_credentials(anoncred);
	gnutls_certificate_free_credentials(x509_cred);

	gnutls_global_deinit();
}
Exemple #18
0
Fichier : psk.c Projet : sqs/gnutls
int
main (int argc, char **argv)
{
  gaainfo info;
  int ret;
  struct passwd *pwd;
  unsigned char key[MAX_KEY_SIZE];
  char hex_key[MAX_KEY_SIZE * 2 + 1];
  gnutls_datum_t dkey;
  size_t hex_key_size = sizeof (hex_key);

  set_program_name (argv[0]);

  if ((ret = gnutls_global_init ()) < 0)
    {
      fprintf (stderr, "global_init: %s\n", gnutls_strerror (ret));
      exit (1);
    }

  umask (066);

  if (gaa (argc, argv, &info) != -1)
    {
      fprintf (stderr, "Error in the arguments.\n");
      return -1;
    }

  if (info.passwd == NULL)
    info.passwd = (char *) KPASSWD;

  if (info.username == NULL)
    {
#ifndef _WIN32
      pwd = getpwuid (getuid ());

      if (pwd == NULL)
        {
          fprintf (stderr, "No such user\n");
          return -1;
        }

      info.username = pwd->pw_name;
#else
      fprintf (stderr, "Please specify a user\n");
      return -1;
#endif
    }

  if (info.key_size > MAX_KEY_SIZE)
    {
      fprintf (stderr, "Key size is too long\n");
      exit (1);
    }

  if (info.key_size < 1)
    info.key_size = 16;

  printf ("Generating a random key for user '%s'\n", info.username);

  ret = gnutls_rnd (GNUTLS_RND_RANDOM, (char *) key, info.key_size);
  if (ret < 0)
    {
      fprintf (stderr, "Not enough randomness\n");
      exit (1);
    }

  dkey.data = key;
  dkey.size = info.key_size;

  ret = gnutls_hex_encode (&dkey, hex_key, &hex_key_size);
  if (ret < 0)
    {
      fprintf (stderr, "HEX encoding error\n");
      exit (1);
    }

  ret = write_key (info.username, hex_key, hex_key_size, info.passwd);
  if (ret == 0)
    printf ("Key stored to %s\n", info.passwd);

  return ret;
}
static void server(int fd)
{
	int ret, csend = 0;
	gnutls_anon_server_credentials_t anoncred;
	char buffer[MAX_BUF + 1];
	gnutls_datum_t cookie_key;
	gnutls_dtls_prestate_st prestate;
	gnutls_session_t session;

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

	if (debug) {
		gnutls_global_set_log_function(server_log_func);
		gnutls_global_set_log_level(4711);
	}

	ret = gnutls_key_generate(&cookie_key, GNUTLS_COOKIE_KEY_SIZE);
	if (ret < 0) {
		fail("Cannot generate key: %s\n", gnutls_strerror(ret));
		terminate();
	}

	gnutls_anon_allocate_server_credentials(&anoncred);

	gnutls_init(&session, GNUTLS_SERVER | GNUTLS_DATAGRAM);
	gnutls_handshake_set_timeout(session, 20 * 1000);
	gnutls_dtls_set_mtu(session, 1500);

	/* avoid calling all the priority functions, since the defaults
	 * are adequate.
	 */
	gnutls_priority_set_direct(session,
				   "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL",
				   NULL);

	gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred);

	gnutls_transport_set_int(session, fd);
	gnutls_transport_set_push_function(session, push);

	for (;;) {
		ret = recv(fd, buffer, sizeof(buffer), MSG_PEEK);
		if (ret < 0) {
			fail("Cannot receive data\n");
			terminate();
		}

		memset(&prestate, 0, sizeof(prestate));
		ret =
		    gnutls_dtls_cookie_verify(&cookie_key, CLI_ADDR,
					      CLI_ADDR_LEN, buffer, ret,
					      &prestate);
		if (ret < 0) {	/* cookie not valid */
			if (debug)
				success("Sending hello verify request\n");

			ret =
			    gnutls_dtls_cookie_send(&cookie_key, CLI_ADDR,
						    CLI_ADDR_LEN,
						    &prestate,
						    (gnutls_transport_ptr_t)
						    (long) fd, push);
			if (ret < 0) {
				fail("Cannot send data\n");
				terminate();
			}

			/* discard peeked data */
			recv(fd, buffer, sizeof(buffer), 0);
			csend++;

			if (csend > 2) {
				fail("too many cookies sent\n");
				terminate();
			}

			continue;
		}

		/* success */
		break;
	}

	gnutls_dtls_prestate_set(session, &prestate);

	do {
		ret = gnutls_handshake(session);
	}
	while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
	if (ret < 0) {
		close(fd);
		gnutls_deinit(session);
		fail("server: Handshake has failed (%s)\n\n",
		     gnutls_strerror(ret));
		terminate();
	}
	if (debug)
		success("server: Handshake was completed\n");

	if (debug)
		success("server: TLS version is: %s\n",
			gnutls_protocol_get_name
			(gnutls_protocol_get_version(session)));

	/* see the Getting peer's information example */
	/* print_info(session); */

	do {
		ret = gnutls_record_send(session, buffer, sizeof(buffer));
	} while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);

	if (ret < 0) {
		close(fd);
		gnutls_deinit(session);
		fail("server: data sending has failed (%s)\n\n",
		     gnutls_strerror(ret));
		terminate();
	}


	/* do not wait for the peer to close the connection.
	 */
	gnutls_bye(session, GNUTLS_SHUT_WR);

	close(fd);
	gnutls_deinit(session);

	gnutls_anon_free_server_credentials(anoncred);
	gnutls_free(cookie_key.data);

	gnutls_global_deinit();

	if (debug)
		success("server: finished\n");
}
Exemple #20
0
void TLSClient::connect (const std::string& host, const std::string& port)
{
  // Store the host name, so the verification callback can access it during the
  // handshake below.
  gnutls_session_set_ptr (_session, (void*) host.c_str ());

  // use IPv4 or IPv6, does not matter.
  struct addrinfo hints = {0};
  hints.ai_family   = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags    = AI_PASSIVE; // use my IP

  struct addrinfo* res;
  if (::getaddrinfo (host.c_str (), port.c_str (), &hints, &res) != 0)
    throw std::string (::gai_strerror (errno));

  // Try them all, stop on success.
  struct addrinfo* p;
  for (p = res; p != NULL; p = p->ai_next)
  {
    if ((_socket = ::socket (p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
      continue;

    // When a socket is closed, it remains unavailable for a while (netstat -an).
    // Setting SO_REUSEADDR allows this program to assume control of a closed,
    // but unavailable socket.
    int on = 1;
    if (::setsockopt (_socket,
                      SOL_SOCKET,
                      SO_REUSEADDR,
                      (const void*) &on,
                      sizeof (on)) == -1)
      throw std::string (::strerror (errno));

    if (::connect (_socket, p->ai_addr, p->ai_addrlen) == -1)
      continue;

    break;
  }

  free (res);

  if (p == NULL)
    throw std::string ("Could not connect to ") + host + " " + port;

#if GNUTLS_VERSION_NUMBER >= 0x030109
  gnutls_transport_set_int (_session, _socket);
#else
  gnutls_transport_set_ptr (_session, (gnutls_transport_ptr_t) (long) _socket);
#endif

  // Perform the TLS handshake
  int ret;
  do
  {
    ret = gnutls_handshake (_session);
  }
  while (ret < 0 && gnutls_error_is_fatal (ret) == 0);
  if (ret < 0)
    throw std::string ("Handshake failed.  ") + gnutls_strerror (ret);

  if (_debug)
  {
#if GNUTLS_VERSION_NUMBER >= 0x03010a
    char* desc = gnutls_session_get_desc (_session);
    std::cout << "c: INFO Handshake was completed: " << desc << "\n";
    gnutls_free (desc);
#else
    std::cout << "c: INFO Handshake was completed.\n";
#endif
  }
}
Exemple #21
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);

	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);

	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);

	/* 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);
		}
	}

	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");
	}
}
Exemple #22
0
void TLSClient::recv (std::string& data)
{
  data = "";          // No appending of data.
  int received = 0;

  // Get the encoded length.
  unsigned char header[4] = {0};
  do
  {
    received = gnutls_record_recv (_session, header, 4);
  }
  while (received > 0 &&
         (errno == GNUTLS_E_INTERRUPTED ||
          errno == GNUTLS_E_AGAIN));

  int total = received;

  // Decode the length.
  unsigned long expected = (header[0]<<24) |
                           (header[1]<<16) |
                           (header[2]<<8) |
                            header[3];
  if (_debug)
    std::cout << "c: INFO expecting " << expected << " bytes.\n";

  // TODO This would be a good place to assert 'expected < _limit'.

  // Arbitrary buffer size.
  char buffer[MAX_BUF];

  // Keep reading until no more data.  Concatenate chunks of data if a) the
  // read was interrupted by a signal, and b) if there is more data than
  // fits in the buffer.
  do
  {
    do
    {
      received = gnutls_record_recv (_session, buffer, MAX_BUF - 1);
    }
    while (received > 0 &&
           (errno == GNUTLS_E_INTERRUPTED ||
            errno == GNUTLS_E_AGAIN));

    // Other end closed the connection.
    if (received == 0)
    {
      if (_debug)
        std::cout << "c: INFO Peer has closed the TLS connection\n";
      break;
    }

    // Something happened.
    if (received < 0 && gnutls_error_is_fatal (received) == 0)
    {
      if (_debug)
      std::cout << "c: WARNING " << gnutls_strerror (received) << "\n";
    }

    else if (received < 0)
      throw std::string (gnutls_strerror (received));

    buffer [received] = '\0';
    data += buffer;
    total += received;

    // Stop at defined limit.
    if (_limit && total > _limit)
      break;
  }
  while (received > 0 && total < (int) expected);

  if (_debug)
    std::cout << "c: INFO Receiving 'XXXX"
              << data.c_str ()
              << "' (" << total << " bytes)"
              << std::endl;
}
Exemple #23
0
int
qcrypto_tls_creds_get_dh_params_file(QCryptoTLSCreds *creds,
                                     const char *filename,
                                     gnutls_dh_params_t *dh_params,
                                     Error **errp)
{
    int ret;

    trace_qcrypto_tls_creds_load_dh(creds, filename ? filename : "<generated>");

    if (filename == NULL) {
        ret = gnutls_dh_params_init(dh_params);
        if (ret < 0) {
            error_setg(errp, "Unable to initialize DH parameters: %s",
                       gnutls_strerror(ret));
            return -1;
        }
        ret = gnutls_dh_params_generate2(*dh_params, DH_BITS);
        if (ret < 0) {
            gnutls_dh_params_deinit(*dh_params);
            *dh_params = NULL;
            error_setg(errp, "Unable to generate DH parameters: %s",
                       gnutls_strerror(ret));
            return -1;
        }
    } else {
        GError *gerr = NULL;
        gchar *contents;
        gsize len;
        gnutls_datum_t data;
        if (!g_file_get_contents(filename,
                                 &contents,
                                 &len,
                                 &gerr)) {

            error_setg(errp, "%s", gerr->message);
            g_error_free(gerr);
            return -1;
        }
        data.data = (unsigned char *)contents;
        data.size = len;
        ret = gnutls_dh_params_init(dh_params);
        if (ret < 0) {
            g_free(contents);
            error_setg(errp, "Unable to initialize DH parameters: %s",
                       gnutls_strerror(ret));
            return -1;
        }
        ret = gnutls_dh_params_import_pkcs3(*dh_params,
                                            &data,
                                            GNUTLS_X509_FMT_PEM);
        g_free(contents);
        if (ret < 0) {
            gnutls_dh_params_deinit(*dh_params);
            *dh_params = NULL;
            error_setg(errp, "Unable to load DH parameters from %s: %s",
                       filename, gnutls_strerror(ret));
            return -1;
        }
    }

    return 0;
}
int tls_global_set_params(void *tls_ctx,
			  const struct tls_connection_params *params)
{
	struct tls_global *global = tls_ctx;
	int ret;

	/* Currently, global parameters are only set when running in server
	 * mode. */
	global->server = 1;

	if (global->params_set) {
		gnutls_certificate_free_credentials(global->xcred);
		global->params_set = 0;
	}

	ret = gnutls_certificate_allocate_credentials(&global->xcred);
	if (ret) {
		wpa_printf(MSG_DEBUG, "Failed to allocate global credentials "
			   "%s", gnutls_strerror(ret));
		return -1;
	}

	if (params->ca_cert) {
		ret = gnutls_certificate_set_x509_trust_file(
			global->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
		if (ret < 0) {
			wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
				   "in PEM format: %s", params->ca_cert,
				   gnutls_strerror(ret));
			ret = gnutls_certificate_set_x509_trust_file(
				global->xcred, params->ca_cert,
				GNUTLS_X509_FMT_DER);
			if (ret < 0) {
				wpa_printf(MSG_DEBUG, "Failed to read CA cert "
					   "'%s' in DER format: %s",
					   params->ca_cert,
					   gnutls_strerror(ret));
				goto fail;
			}
		}

		if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
			gnutls_certificate_set_verify_flags(
				global->xcred,
				GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
		}

#if LIBGNUTLS_VERSION_NUMBER >= 0x020800
		if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
			gnutls_certificate_set_verify_flags(
				global->xcred,
				GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
		}
#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x020800 */
	}

	if (params->client_cert && params->private_key) {
		/* TODO: private_key_passwd? */
		ret = gnutls_certificate_set_x509_key_file(
			global->xcred, params->client_cert,
			params->private_key, GNUTLS_X509_FMT_PEM);
		if (ret < 0) {
			wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
				   "in PEM format: %s", gnutls_strerror(ret));
			ret = gnutls_certificate_set_x509_key_file(
				global->xcred, params->client_cert,
				params->private_key, GNUTLS_X509_FMT_DER);
			if (ret < 0) {
				wpa_printf(MSG_DEBUG, "Failed to read client "
					   "cert/key in DER format: %s",
					   gnutls_strerror(ret));
				goto fail;
			}
		}
	} else if (params->private_key) {
		int pkcs12_ok = 0;
#ifdef PKCS12_FUNCS
		/* Try to load in PKCS#12 format */
#if LIBGNUTLS_VERSION_NUMBER >= 0x010302
		ret = gnutls_certificate_set_x509_simple_pkcs12_file(
			global->xcred, params->private_key,
			GNUTLS_X509_FMT_DER, params->private_key_passwd);
		if (ret != 0) {
			wpa_printf(MSG_DEBUG, "Failed to load private_key in "
				   "PKCS#12 format: %s", gnutls_strerror(ret));
			goto fail;
		} else
			pkcs12_ok = 1;
#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
#endif /* PKCS12_FUNCS */

		if (!pkcs12_ok) {
			wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
				   "included");
			goto fail;
		}
	}

	global->params_set = 1;

	return 0;

fail:
	gnutls_certificate_free_credentials(global->xcred);
	return -1;
}
Exemple #25
0
LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection)
{
	if (!connection || connection->ssl_data)
		return IDEVICE_E_INVALID_ARG;

	idevice_error_t ret = IDEVICE_E_SSL_ERROR;
#ifdef HAVE_OPENSSL
	uint32_t return_me = 0;
#else
	int return_me = 0;
#endif
	plist_t pair_record = NULL;

	userpref_read_pair_record(connection->udid, &pair_record);
	if (!pair_record) {
		debug_info("ERROR: Failed enabling SSL. Unable to read pair record for udid %s.", connection->udid);
		return ret;
	}

#ifdef HAVE_OPENSSL
	key_data_t root_cert = { NULL, 0 };
	key_data_t root_privkey = { NULL, 0 };

	pair_record_import_crt_with_name(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert);
	pair_record_import_key_with_name(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, &root_privkey);

	if (pair_record)
		plist_free(pair_record);

	BIO *ssl_bio = BIO_new(BIO_s_socket());
	if (!ssl_bio) {
		debug_info("ERROR: Could not create SSL bio.");
		return ret;
	}
	BIO_set_fd(ssl_bio, (int)(long)connection->data, BIO_NOCLOSE);

	SSL_CTX *ssl_ctx = SSL_CTX_new(TLSv1_method());
	if (ssl_ctx == NULL) {
		debug_info("ERROR: Could not create SSL context.");
		BIO_free(ssl_bio);
		return ret;
	}

	BIO* membp;
	X509* rootCert = NULL;
	membp = BIO_new_mem_buf(root_cert.data, root_cert.size);
	PEM_read_bio_X509(membp, &rootCert, NULL, NULL);
	BIO_free(membp);
	if (SSL_CTX_use_certificate(ssl_ctx, rootCert) != 1) {
		debug_info("WARNING: Could not load RootCertificate");
	}
	X509_free(rootCert);
	free(root_cert.data);

	RSA* rootPrivKey = NULL;
	membp = BIO_new_mem_buf(root_privkey.data, root_privkey.size);
	PEM_read_bio_RSAPrivateKey(membp, &rootPrivKey, NULL, NULL);
	BIO_free(membp);
	if (SSL_CTX_use_RSAPrivateKey(ssl_ctx, rootPrivKey) != 1) {
		debug_info("WARNING: Could not load RootPrivateKey");
	}
	RSA_free(rootPrivKey);
	free(root_privkey.data);

	SSL *ssl = SSL_new(ssl_ctx);
	if (!ssl) {
		debug_info("ERROR: Could not create SSL object");
		BIO_free(ssl_bio);
		SSL_CTX_free(ssl_ctx);
		return ret;
	}
	SSL_set_connect_state(ssl);
	SSL_set_verify(ssl, 0, ssl_verify_callback);
	SSL_set_bio(ssl, ssl_bio, ssl_bio);

	return_me = SSL_do_handshake(ssl);
	if (return_me != 1) {
		debug_info("ERROR in SSL_do_handshake: %s", ssl_error_to_string(SSL_get_error(ssl, return_me)));
		SSL_free(ssl);
		SSL_CTX_free(ssl_ctx);
	} else {
		ssl_data_t ssl_data_loc = (ssl_data_t)malloc(sizeof(struct ssl_data_private));
		ssl_data_loc->session = ssl;
		ssl_data_loc->ctx = ssl_ctx;
		connection->ssl_data = ssl_data_loc;
		ret = IDEVICE_E_SUCCESS;
		debug_info("SSL mode enabled, cipher: %s", SSL_get_cipher(ssl));
	}
	/* required for proper multi-thread clean up to prevent leaks */
	openssl_remove_thread_state();
#else
	ssl_data_t ssl_data_loc = (ssl_data_t)malloc(sizeof(struct ssl_data_private));

	/* Set up GnuTLS... */
	debug_info("enabling SSL mode");
	errno = 0;
	gnutls_certificate_allocate_credentials(&ssl_data_loc->certificate);
#if GNUTLS_VERSION_NUMBER >= 0x020b07
	gnutls_certificate_set_retrieve_function(ssl_data_loc->certificate, internal_cert_callback);
#else
	gnutls_certificate_client_set_retrieve_function(ssl_data_loc->certificate, internal_cert_callback);
#endif
	gnutls_init(&ssl_data_loc->session, GNUTLS_CLIENT);
	gnutls_priority_set_direct(ssl_data_loc->session, "NONE:+VERS-TLS1.0:+ANON-DH:+RSA:+AES-128-CBC:+AES-256-CBC:+SHA1:+MD5:+COMP-NULL", NULL);
	gnutls_credentials_set(ssl_data_loc->session, GNUTLS_CRD_CERTIFICATE, ssl_data_loc->certificate);
	gnutls_session_set_ptr(ssl_data_loc->session, ssl_data_loc);

	gnutls_x509_crt_init(&ssl_data_loc->root_cert);
	gnutls_x509_crt_init(&ssl_data_loc->host_cert);
	gnutls_x509_privkey_init(&ssl_data_loc->root_privkey);
	gnutls_x509_privkey_init(&ssl_data_loc->host_privkey);

	pair_record_import_crt_with_name(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, ssl_data_loc->root_cert);
	pair_record_import_crt_with_name(pair_record, USERPREF_HOST_CERTIFICATE_KEY, ssl_data_loc->host_cert);
	pair_record_import_key_with_name(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, ssl_data_loc->root_privkey);
	pair_record_import_key_with_name(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, ssl_data_loc->host_privkey);

	if (pair_record)
		plist_free(pair_record);

	debug_info("GnuTLS step 1...");
	gnutls_transport_set_ptr(ssl_data_loc->session, (gnutls_transport_ptr_t)connection);
	debug_info("GnuTLS step 2...");
	gnutls_transport_set_push_function(ssl_data_loc->session, (gnutls_push_func) & internal_ssl_write);
	debug_info("GnuTLS step 3...");
	gnutls_transport_set_pull_function(ssl_data_loc->session, (gnutls_pull_func) & internal_ssl_read);
	debug_info("GnuTLS step 4 -- now handshaking...");
	if (errno) {
		debug_info("WARNING: errno says %s before handshake!", strerror(errno));
	}

	do {
		return_me = gnutls_handshake(ssl_data_loc->session);
	} while(return_me == GNUTLS_E_AGAIN || return_me == GNUTLS_E_INTERRUPTED);

	debug_info("GnuTLS handshake done...");

	if (return_me != GNUTLS_E_SUCCESS) {
		internal_ssl_cleanup(ssl_data_loc);
		free(ssl_data_loc);
		debug_info("GnuTLS reported something wrong: %s", gnutls_strerror(return_me));
		debug_info("oh.. errno says %s", strerror(errno));
	} else {
		connection->ssl_data = ssl_data_loc;
		ret = IDEVICE_E_SUCCESS;
		debug_info("SSL mode enabled");
	}
#endif
	return ret;
}
struct wpabuf * tls_connection_handshake(void *tls_ctx,
					 struct tls_connection *conn,
					 const struct wpabuf *in_data,
					 struct wpabuf **appl_data)
{
	struct tls_global *global = tls_ctx;
	struct wpabuf *out_data;
	int ret;

	if (appl_data)
		*appl_data = NULL;

	if (in_data && wpabuf_len(in_data) > 0) {
		if (conn->pull_buf) {
			wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
				   "pull_buf", __func__,
				   (unsigned long) wpabuf_len(conn->pull_buf));
			wpabuf_free(conn->pull_buf);
		}
		conn->pull_buf = wpabuf_dup(in_data);
		if (conn->pull_buf == NULL)
			return NULL;
		conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
	}

	ret = gnutls_handshake(conn->session);
	if (ret < 0) {
		switch (ret) {
		case GNUTLS_E_AGAIN:
			if (global->server && conn->established &&
			    conn->push_buf == NULL) {
				/* Need to return something to trigger
				 * completion of EAP-TLS. */
				conn->push_buf = wpabuf_alloc(0);
			}
			break;
		case GNUTLS_E_FATAL_ALERT_RECEIVED:
			wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
				   __func__, gnutls_alert_get_name(
					   gnutls_alert_get(conn->session)));
			conn->read_alerts++;
			/* continue */
		default:
			wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
				   "-> %s", __func__, gnutls_strerror(ret));
			conn->failed++;
		}
	} else {
		size_t size;
		gnutls_alert_description_t err;

		if (conn->verify_peer &&
		    tls_connection_verify_peer(conn, &err)) {
			wpa_printf(MSG_INFO, "TLS: Peer certificate chain "
				   "failed validation");
			conn->failed++;
			gnutls_alert_send(conn->session, GNUTLS_AL_FATAL, err);
			goto out;
		}

		wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
		conn->established = 1;
		if (conn->push_buf == NULL) {
			/* Need to return something to get final TLS ACK. */
			conn->push_buf = wpabuf_alloc(0);
		}

		gnutls_session_get_data(conn->session, NULL, &size);
		if (global->session_data == NULL ||
		    global->session_data_size < size) {
			os_free(global->session_data);
			global->session_data = os_malloc(size);
		}
		if (global->session_data) {
			global->session_data_size = size;
			gnutls_session_get_data(conn->session,
						global->session_data,
						&global->session_data_size);
		}

		if (conn->pull_buf && appl_data)
			*appl_data = gnutls_get_appl_data(conn);
	}

out:
	out_data = conn->push_buf;
	conn->push_buf = NULL;
	return out_data;
}
static void fusion_tls_connection_handle_error (FusionTLSConnection* self, int ecode, gint where, GError** error) {
	gboolean _tmp0_ = FALSE;
	int _tmp1_ = 0;
	gboolean _tmp3_ = FALSE;
	gboolean _tmp8_ = FALSE;
	int _tmp9_ = 0;
	gboolean _tmp12_ = FALSE;
	GError * _inner_error_ = NULL;
	g_return_if_fail (self != NULL);
	_tmp1_ = ecode;
	if (_tmp1_ == GNUTLS_E_WARNING_ALERT_RECEIVED) {
		_tmp0_ = TRUE;
	} else {
		int _tmp2_ = 0;
		_tmp2_ = ecode;
		_tmp0_ = _tmp2_ == GNUTLS_E_FATAL_ALERT_RECEIVED;
	}
	_tmp3_ = _tmp0_;
	if (_tmp3_) {
		gnutls_alert_description_t alert = 0;
		struct gnutls_session_int* _tmp4_ = NULL;
		gnutls_alert_description_t _tmp5_ = 0;
		gnutls_alert_description_t _tmp6_ = 0;
		const gchar* _tmp7_ = NULL;
		_tmp4_ = self->tls_session;
		_tmp5_ = gnutls_alert_get (_tmp4_);
		alert = _tmp5_;
		_tmp6_ = alert;
		_tmp7_ = gnutls_alert_get_name (_tmp6_);
		g_warning ("TLSConnection.vala:74: TLS handshake alert: %s", _tmp7_);
	}
	_tmp9_ = ecode;
	if (_tmp9_ < 0) {
		int _tmp10_ = 0;
		gboolean _tmp11_ = FALSE;
		_tmp10_ = ecode;
		_tmp11_ = gnutls_error_is_fatal (_tmp10_);
		_tmp8_ = _tmp11_;
	} else {
		_tmp8_ = FALSE;
	}
	_tmp12_ = _tmp8_;
	if (_tmp12_) {
		gint _tmp13_ = 0;
		_tmp13_ = where;
		switch (_tmp13_) {
			case 0:
			{
				int _tmp14_ = 0;
				const gchar* _tmp15_ = NULL;
				GError* _tmp16_ = NULL;
				_tmp14_ = ecode;
				_tmp15_ = gnutls_strerror (_tmp14_);
				_tmp16_ = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, "Handshake failed: %s", _tmp15_);
				_inner_error_ = _tmp16_;
				if (_inner_error_->domain == G_IO_ERROR) {
					g_propagate_error (error, _inner_error_);
					return;
				} else {
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
					g_clear_error (&_inner_error_);
					return;
				}
			}
			case 1:
			{
				int _tmp17_ = 0;
				const gchar* _tmp18_ = NULL;
				GError* _tmp19_ = NULL;
				_tmp17_ = ecode;
				_tmp18_ = gnutls_strerror (_tmp17_);
				_tmp19_ = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, "Receive failed: %s", _tmp18_);
				_inner_error_ = _tmp19_;
				if (_inner_error_->domain == G_IO_ERROR) {
					g_propagate_error (error, _inner_error_);
					return;
				} else {
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
					g_clear_error (&_inner_error_);
					return;
				}
			}
			case 2:
			{
				int _tmp20_ = 0;
				const gchar* _tmp21_ = NULL;
				GError* _tmp22_ = NULL;
				_tmp20_ = ecode;
				_tmp21_ = gnutls_strerror (_tmp20_);
				_tmp22_ = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, "Send failed: %s", _tmp21_);
				_inner_error_ = _tmp22_;
				if (_inner_error_->domain == G_IO_ERROR) {
					g_propagate_error (error, _inner_error_);
					return;
				} else {
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
					g_clear_error (&_inner_error_);
					return;
				}
			}
			default:
			{
				g_assert_not_reached ();
			}
		}
	}
}
Exemple #28
0
static void test_ciphersuite(const char *cipher_prio, int size)
{
	/* Server stuff. */
	gnutls_anon_server_credentials_t s_anoncred;
	gnutls_certificate_credentials_t c_certcred, s_certcred;
	gnutls_session_t server;
	int sret, cret;
	const char *str;
	/* Client stuff. */
	gnutls_anon_client_credentials_t c_anoncred;
	gnutls_session_t client;
	/* Need to enable anonymous KX specifically. */
	int ret;
	struct benchmark_st st;
	gnutls_packet_t packet;
	const char *name;

	/* Init server */
	gnutls_anon_allocate_server_credentials(&s_anoncred);
	gnutls_certificate_allocate_credentials(&s_certcred);

	gnutls_certificate_set_x509_key_mem(s_certcred, &server_cert,
					    &server_key,
					    GNUTLS_X509_FMT_PEM);
	gnutls_certificate_set_x509_key_mem(s_certcred, &server_ecc_cert,
					    &server_ecc_key,
					    GNUTLS_X509_FMT_PEM);

	gnutls_init(&server, GNUTLS_SERVER);
	ret = gnutls_priority_set_direct(server, cipher_prio, &str);
	if (ret < 0) {
		fprintf(stderr, "Error in %s\n", str);
		exit(1);
	}
	gnutls_credentials_set(server, GNUTLS_CRD_ANON, s_anoncred);
	gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, s_certcred);
	gnutls_transport_set_push_function(server, server_push);
	gnutls_transport_set_pull_function(server, server_pull);
	gnutls_transport_set_ptr(server, (gnutls_transport_ptr_t) server);
	reset_buffers();

	/* Init client */
	gnutls_anon_allocate_client_credentials(&c_anoncred);
	gnutls_certificate_allocate_credentials(&c_certcred);
	gnutls_init(&client, GNUTLS_CLIENT);

	ret = gnutls_priority_set_direct(client, cipher_prio, &str);
	if (ret < 0) {
		fprintf(stderr, "Error in %s\n", str);
		exit(1);
	}
	gnutls_credentials_set(client, GNUTLS_CRD_ANON, c_anoncred);
	gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, c_certcred);
	gnutls_transport_set_push_function(client, client_push);
	gnutls_transport_set_pull_function(client, client_pull);
	gnutls_transport_set_ptr(client, (gnutls_transport_ptr_t) client);

	HANDSHAKE(client, server);

	name = gnutls_cipher_get_name(gnutls_cipher_get(server));
	fprintf(stdout, "%30s - %s  ", name, gnutls_protocol_get_name(
		gnutls_protocol_get_version(server)));
	fflush(stdout);

	ret = gnutls_rnd(GNUTLS_RND_NONCE, buffer, sizeof(buffer));
	if (ret < 0) {
		fprintf(stderr, "Error in %s\n", str);
		exit(1);
	}

	start_benchmark(&st);

	do {
		do {
			ret = gnutls_record_send(client, buffer, size);
		}
		while (ret == GNUTLS_E_AGAIN);

		if (ret < 0) {
			fprintf(stderr, "Failed sending to server\n");
			exit(1);
		}

		do {
			ret =
			    gnutls_record_recv_packet(server, &packet);
		}
		while (ret == GNUTLS_E_AGAIN);

		if (ret < 0) {
			fprintf(stderr, "Failed receiving from client: %s\n", gnutls_strerror(ret));
			exit(1);
		}

		st.size += size;
		gnutls_packet_deinit(packet);
	}
	while (benchmark_must_finish == 0);

	stop_benchmark(&st, NULL, 1);

	gnutls_bye(client, GNUTLS_SHUT_WR);
	gnutls_bye(server, GNUTLS_SHUT_WR);

	gnutls_deinit(client);
	gnutls_deinit(server);

	gnutls_anon_free_client_credentials(c_anoncred);
	gnutls_anon_free_server_credentials(s_anoncred);
}
int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
                              const struct tls_connection_params *params)
{
        int ret;

        if (conn == NULL || params == NULL)
                return -1;

        os_free(conn->subject_match);
        conn->subject_match = NULL;
        if (params->subject_match) {
                conn->subject_match = os_strdup(params->subject_match);
                if (conn->subject_match == NULL)
                        return -1;
        }

        os_free(conn->altsubject_match);
        conn->altsubject_match = NULL;
        if (params->altsubject_match) {
                conn->altsubject_match = os_strdup(params->altsubject_match);
                if (conn->altsubject_match == NULL)
                        return -1;
        }

        /* TODO: gnutls_certificate_set_verify_flags(xcred, flags); 
         * to force peer validation(?) */

        if (params->ca_cert) {
                conn->verify_peer = 1;
                ret = gnutls_certificate_set_x509_trust_file(
                        conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM);
                if (ret < 0) {
                        wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
                                   "in PEM format: %s", params->ca_cert,
                                   gnutls_strerror(ret));
                        ret = gnutls_certificate_set_x509_trust_file(
                                conn->xcred, params->ca_cert,
                                GNUTLS_X509_FMT_DER);
                        if (ret < 0) {
                                wpa_printf(MSG_DEBUG, "Failed to read CA cert "
                                           "'%s' in DER format: %s",
                                           params->ca_cert,
                                           gnutls_strerror(ret));
                                return -1;
                        }
                }

                if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
                        gnutls_certificate_set_verify_flags(
                                conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
                }

                if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
                        gnutls_certificate_set_verify_flags(
                                conn->xcred,
                                GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
                }
        }

        if (params->client_cert && params->private_key) {
                /* TODO: private_key_passwd? */
                ret = gnutls_certificate_set_x509_key_file(
                        conn->xcred, params->client_cert, params->private_key,
                        GNUTLS_X509_FMT_PEM);
                if (ret < 0) {
                        wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
                                   "in PEM format: %s", gnutls_strerror(ret));
                        ret = gnutls_certificate_set_x509_key_file(
                                conn->xcred, params->client_cert,
                                params->private_key, GNUTLS_X509_FMT_DER);
                        if (ret < 0) {
                                wpa_printf(MSG_DEBUG, "Failed to read client "
                                           "cert/key in DER format: %s",
                                           gnutls_strerror(ret));
                                return ret;
                        }
                }
        } else if (params->private_key) {
                int pkcs12_ok = 0;
#ifdef PKCS12_FUNCS
                /* Try to load in PKCS#12 format */
#if LIBGNUTLS_VERSION_NUMBER >= 0x010302
                ret = gnutls_certificate_set_x509_simple_pkcs12_file(
                        conn->xcred, params->private_key, GNUTLS_X509_FMT_DER,
                        params->private_key_passwd);
                if (ret != 0) {
                        wpa_printf(MSG_DEBUG, "Failed to load private_key in "
                                   "PKCS#12 format: %s", gnutls_strerror(ret));
                        return -1;
                } else
                        pkcs12_ok = 1;
#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
#endif /* PKCS12_FUNCS */

                if (!pkcs12_ok) {
                        wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
                                   "included");
                        return -1;
                }
        }

        conn->tls_ia = params->tls_ia;
        conn->params_set = 1;

        ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
                                     conn->xcred);
        if (ret < 0) {
                wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
                           gnutls_strerror(ret));
        }

#ifdef GNUTLS_IA
        if (conn->iacred_cli)
                gnutls_ia_free_client_credentials(conn->iacred_cli);

        ret = gnutls_ia_allocate_client_credentials(&conn->iacred_cli);
        if (ret) {
                wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s",
                           gnutls_strerror(ret));
                return -1;
        }

        ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA,
                                     conn->iacred_cli);
        if (ret) {
                wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s",
                           gnutls_strerror(ret));
                gnutls_ia_free_client_credentials(conn->iacred_cli);
                conn->iacred_cli = NULL;
                return -1;
        }
#endif /* GNUTLS_IE */

        return ret;
}
Exemple #30
0
/*****************************************************************************
 * tls_ServerCreate:
 *****************************************************************************
 * Allocates a whole server's TLS credentials.
 * Returns NULL on error.
 *****************************************************************************/
static tls_server_t *
gnutls_ServerCreate( tls_t *p_this, const char *psz_cert_path,
                  const char *psz_key_path )
{
    tls_server_t *p_server;
    tls_server_sys_t *p_server_sys;
    int val;

    msg_Dbg( p_this, "Creating TLS server" );

    p_server_sys = (tls_server_sys_t *)malloc( sizeof(struct tls_server_sys_t) );
    if( p_server_sys == NULL )
        return NULL;

    /* Sets server's credentials */
    val = gnutls_certificate_allocate_credentials( &p_server_sys->x509_cred );
    if( val != 0 )
    {
        msg_Err( p_this, "Cannot allocate X509 credentials : %s",
                 gnutls_strerror( val ) );
        free( p_server_sys );
        return NULL;
    }

    val = gnutls_certificate_set_x509_key_file( p_server_sys->x509_cred,
                                                psz_cert_path, psz_key_path,
                                                GNUTLS_X509_FMT_PEM );
    if( val < 0 )
    {
        msg_Err( p_this, "Cannot set certificate chain or private key : %s",
                 gnutls_strerror( val ) );
        gnutls_certificate_free_credentials( p_server_sys->x509_cred );
        free( p_server_sys );
        return NULL;
    }

    /* FIXME: regenerate these regularly */
    val = gnutls_dh_params_init( &p_server_sys->dh_params );
    if( val >= 0 )
    {
        vlc_value_t bits;

        if( var_Get( p_this, "dh-bits", &bits ) != VLC_SUCCESS )
        {
            var_Create( p_this, "dh-bits",
                        VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
            var_Get( p_this, "dh-bits", &bits );
        }

        msg_Dbg( p_this, "Computing Diffie Hellman ciphers parameters" );
        val = gnutls_dh_params_generate2( p_server_sys->dh_params,
                                          bits.i_int );
    }
    if( val < 0 )
    {
        msg_Err( p_this, "Cannot initialize DH cipher suites : %s",
                 gnutls_strerror( val ) );
        gnutls_certificate_free_credentials( p_server_sys->x509_cred );
        free( p_server_sys );
        return NULL;
    }
    msg_Dbg( p_this, "Ciphers parameters computed" );

    gnutls_certificate_set_dh_params( p_server_sys->x509_cred,
                                      p_server_sys->dh_params);

    p_server = (tls_server_t *)malloc( sizeof(struct tls_server_t) );
    if( p_server == NULL )
    {
        free( p_server_sys );
        return NULL;
    }

    p_server->p_tls = p_this;
    p_server->p_sys = p_server_sys;
    p_server->pf_delete = gnutls_ServerDelete;
    p_server->pf_add_CA = gnutls_ServerAddCA;
    p_server->pf_add_CRL = gnutls_ServerAddCRL;
    p_server->pf_session_prepare = gnutls_ServerSessionPrepare;

    return p_server;
}