static void
aes_deinit (void *_ctx)
{
  gnutls_free (_ctx);
}
示例#2
0
int
generate_create_conf (char *tpasswd_conf)
{
  FILE *fd;
  char line[5 * 1024];
  int index = 1;
  gnutls_datum_t g, n;
  gnutls_datum_t str_g, str_n;

  fd = fopen (tpasswd_conf, "w");
  if (fd == NULL)
    {
      fprintf (stderr, "Cannot open file '%s'\n", tpasswd_conf);
      return -1;
    }

  for (index = 1; index <= 3; index++)
    {

      if (index == 1)
	{
	  n = gnutls_srp_1024_group_prime;
	  g = gnutls_srp_1024_group_generator;
	}
      else if (index == 2)
	{
	  n = gnutls_srp_1536_group_prime;
	  g = gnutls_srp_1536_group_generator;
	}
      else
	{
	  n = gnutls_srp_2048_group_prime;
	  g = gnutls_srp_2048_group_generator;
	}

      printf ("\nGroup %d, of %d bits:\n", index, n.size * 8);
      print_num ("Generator", &g);
      print_num ("Prime", &n);

      if (gnutls_srp_base64_encode_alloc (&n, &str_n) < 0)
	{
	  fprintf (stderr, "Could not encode\n");
	  return -1;
	}

      if (gnutls_srp_base64_encode_alloc (&g, &str_g) < 0)
	{
	  fprintf (stderr, "Could not encode\n");
	  return -1;
	}

      sprintf (line, "%d:%s:%s\n", index, str_n.data, str_g.data);

      gnutls_free (str_n.data);
      gnutls_free (str_g.data);

      fwrite (line, 1, strlen (line), fd);

    }

  fclose (fd);

  return 0;

}
示例#3
0
static void
wrap_nettle_cipher_close (void *h)
{
  gnutls_free (h);
}
示例#4
0
void TLSTransaction::init (TLSServer& server)
{
  int ret = gnutls_init (&_session, GNUTLS_SERVER);
  if (ret < 0)
    throw format ("TLS server init error. {1}", gnutls_strerror (ret));

  ret = gnutls_priority_set (_session, server._priorities);
  if (ret < 0)
    throw format ("Error initializing TLS. {1}", gnutls_strerror (ret));

  // Apply the x509 credentials to the current session.
  ret = gnutls_credentials_set (_session, GNUTLS_CRD_CERTIFICATE, server._credentials);
  if (ret < 0)
    throw format ("TLS credentials error. {1}", gnutls_strerror (ret));

  // Store the TLSTransaction instance, so that the verification callback can
  // access it during the handshake below and call the verifcation method.
  gnutls_session_set_ptr (_session, (void*) this);

  // Require client certificate.
  gnutls_certificate_server_set_request (_session, GNUTLS_CERT_REQUIRE);

/*
  // Set maximum compatibility mode. This is only suggested on public
  // webservers that need to trade security for compatibility
  gnutls_session_enable_compatibility_mode (_session);
*/

  struct sockaddr_in sa_cli = {0};
  socklen_t client_len = sizeof sa_cli;
  do
  {
    _socket = accept (server._socket, (struct sockaddr *) &sa_cli, &client_len);
  }
  while (errno == EINTR);

  if (_socket < 0)
    throw std::string (::strerror (errno));

  // Obtain client info.
  char topbuf[512];
  _address = inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf, sizeof (topbuf));
  _port    = ntohs (sa_cli.sin_port);
  if (_debug)
    std::cout << "s: INFO connection from "
              << _address
              << " port "
              << _port
              << "\n";

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

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

#if GNUTLS_VERSION_NUMBER < 0x02090a
  // The automatic verification for the server certificate with
  // gnutls_certificate_set_verify_function does only work with gnutls
  // >=2.9.10. So with older versions we should call the verify function
  // manually after the gnutls handshake.
  ret = verify_certificate ();
  if (ret < 0)
  {
    if (_debug)
      std::cout << "s: ERROR Certificate verification failed.\n";
    throw std::string ("Error initializing TLS.");
  }
#endif

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

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

	gnutls_anon_allocate_server_credentials(&anoncred);

	gnutls_init(&session, GNUTLS_SERVER | GNUTLS_DATAGRAM);
	gnutls_handshake_set_timeout(session, SERV_TIMEOUT * 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_timeout(fd, buffer, sizeof(buffer), MSG_PEEK, SERV_TIMEOUT);
		if (ret < 0) {
			if (try != 0) {
				success("Server was terminated as expected!\n");
				goto exit;
			} else {
				fail("Error receiving first message\n");
				exit(1);
			}
		}
		try++;

		memset(&prestate, 0, sizeof(prestate));
		prestate.record_seq = 105791312;
		prestate.hsk_write_seq = 67166359;
		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");
				exit(1);
			}

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

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

			continue;
		}

		/* success */
		break;
	}

	fail("Shouldn't have reached here\n");
	exit(1);
 exit:
	gnutls_deinit(session);
	gnutls_free(cookie_key.data);

	gnutls_anon_free_server_credentials(anoncred);

	gnutls_global_deinit();
}
int main(void)
{
        int ret, sd, ii;
        gnutls_session_t session;
        gnutls_priority_t priorities_cache;
        char buffer[MAX_BUF + 1];
        gnutls_certificate_credentials_t xcred;
        /* Allow connections to servers that have OpenPGP keys as well.
         */

        gnutls_global_init();
        /* PKCS11 private key operations might require PIN.
         * Register a callback.
         */
        gnutls_pkcs11_set_pin_function(pin_callback, NULL);

        /* X509 stuff */
        gnutls_certificate_allocate_credentials(&xcred);

        /* priorities */
        gnutls_priority_init(&priorities_cache, "NORMAL", NULL);

        /* sets the trusted cas file
         */
        gnutls_certificate_set_x509_trust_file(xcred, CAFILE,
                                               GNUTLS_X509_FMT_PEM);

        gnutls_certificate_set_x509_key_file(xcred, CERT_URL, KEY_URL,
                                             GNUTLS_X509_FMT_DER);

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

        /* Use default priorities */
        gnutls_priority_set(session, priorities_cache);

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

        /* connect to the peer
         */
        sd = tcp_connect();

        gnutls_transport_set_int(session, sd);

        /* Perform the TLS handshake
         */
        ret = gnutls_handshake(session);

        if (ret < 0) {
                fprintf(stderr, "*** Handshake failed\n");
                gnutls_perror(ret);
                goto end;
        } else {
                char *desc;

                desc = gnutls_session_get_desc(session);
                printf("- Session info: %s\n", desc);
                gnutls_free(desc);
        }

        gnutls_record_send(session, MSG, strlen(MSG));

        ret = gnutls_record_recv(session, buffer, MAX_BUF);
        if (ret == 0) {
                printf("- Peer has closed the TLS connection\n");
                goto end;
        } else if (ret < 0) {
                fprintf(stderr, "*** Error: %s\n", gnutls_strerror(ret));
                goto end;
        }

        printf("- Received %d bytes: ", ret);
        for (ii = 0; ii < ret; ii++) {
                fputc(buffer[ii], stdout);
        }
        fputs("\n", stdout);

        gnutls_bye(session, GNUTLS_SHUT_RDWR);

      end:

        tcp_close(sd);

        gnutls_deinit(session);

        gnutls_certificate_free_credentials(xcred);
        gnutls_priority_deinit(priorities_cache);

        gnutls_global_deinit();

        return 0;
}
示例#7
0
/**
 * gnutls_pkcs12_simple_parse:
 * @p12: the PKCS12 blob.
 * @password: optional password used to decrypt PKCS12 blob, bags and keys.
 * @key: a structure to store the parsed private key.
 * @chain: the corresponding to key certificate chain (may be %NULL)
 * @chain_len: will be updated with the number of additional (may be %NULL)
 * @extra_certs: optional pointer to receive an array of additional
 *               certificates found in the PKCS12 blob (may be %NULL).
 * @extra_certs_len: will be updated with the number of additional
 *                   certs (may be %NULL).
 * @crl: an optional structure to store the parsed CRL (may be %NULL).
 * @flags: should be zero or one of GNUTLS_PKCS12_SP_*
 *
 * This function parses a PKCS12 blob in @p12blob and extracts the
 * private key, the corresponding certificate chain, and any additional
 * certificates and a CRL.
 *
 * The @extra_certs_ret and @extra_certs_len parameters are optional
 * and both may be set to %NULL. If either is non-%NULL, then both must
 * be set.
 * 
 * Encrypted PKCS12 bags and PKCS8 private keys are supported.  However,
 * only password based security, and the same password for all
 * operations, are supported.
 *
 * A PKCS12 file may contain many keys and/or certificates, and there
 * is no way to identify which key/certificate pair you want.  You
 * should make sure the PKCS12 file only contain one key/certificate
 * pair and/or one CRL.
 *
 * It is believed that the limitations of this function are acceptable
 * for common usage, and that any more flexibility would introduce
 * complexity that would make it harder to use this functionality at
 * all.
 *
 * If the provided structure has encrypted fields but no password
 * is provided then this function returns %GNUTLS_E_DECRYPTION_FAILED.
 *
 * Note that normally the chain constructed does not include self signed
 * certificates, to comply with TLS' requirements. If, however, the flag 
 * %GNUTLS_PKCS12_SP_INCLUDE_SELF_SIGNED is specified then
 * self signed certificates will be included in the chain.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.1
 **/
int
gnutls_pkcs12_simple_parse(gnutls_pkcs12_t p12,
			   const char *password,
			   gnutls_x509_privkey_t * key,
			   gnutls_x509_crt_t ** chain,
			   unsigned int *chain_len,
			   gnutls_x509_crt_t ** extra_certs,
			   unsigned int *extra_certs_len,
			   gnutls_x509_crl_t * crl, unsigned int flags)
{
	gnutls_pkcs12_bag_t bag = NULL;
	gnutls_x509_crt_t *_extra_certs = NULL;
	unsigned int _extra_certs_len = 0;
	gnutls_x509_crt_t *_chain = NULL;
	unsigned int _chain_len = 0;
	int idx = 0;
	int ret;
	size_t cert_id_size = 0;
	size_t key_id_size = 0;
	uint8_t cert_id[20];
	uint8_t key_id[20];
	int privkey_ok = 0;
	unsigned int i;

	*key = NULL;

	if (crl)
		*crl = NULL;

	/* find the first private key */
	for (;;) {
		int elements_in_bag;
		int i;

		ret = gnutls_pkcs12_bag_init(&bag);
		if (ret < 0) {
			bag = NULL;
			gnutls_assert();
			goto done;
		}

		ret = gnutls_pkcs12_get_bag(p12, idx, bag);
		if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
			break;
		if (ret < 0) {
			gnutls_assert();
			goto done;
		}

		ret = gnutls_pkcs12_bag_get_type(bag, 0);
		if (ret < 0) {
			gnutls_assert();
			goto done;
		}

		if (ret == GNUTLS_BAG_ENCRYPTED) {
			if (password == NULL) {
				ret =
				    gnutls_assert_val
				    (GNUTLS_E_DECRYPTION_FAILED);
				goto done;
			}

			ret = gnutls_pkcs12_bag_decrypt(bag, password);
			if (ret < 0) {
				gnutls_assert();
				goto done;
			}
		}

		elements_in_bag = gnutls_pkcs12_bag_get_count(bag);
		if (elements_in_bag < 0) {
			gnutls_assert();
			goto done;
		}

		for (i = 0; i < elements_in_bag; i++) {
			int type;
			gnutls_datum_t data;

			type = gnutls_pkcs12_bag_get_type(bag, i);
			if (type < 0) {
				gnutls_assert();
				goto done;
			}

			ret = gnutls_pkcs12_bag_get_data(bag, i, &data);
			if (ret < 0) {
				gnutls_assert();
				goto done;
			}

			switch (type) {
			case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
				if (password == NULL) {
					ret =
					    gnutls_assert_val
					    (GNUTLS_E_DECRYPTION_FAILED);
					goto done;
				}

			case GNUTLS_BAG_PKCS8_KEY:
				if (*key != NULL) {	/* too simple to continue */
					gnutls_assert();
					break;
				}

				ret = gnutls_x509_privkey_init(key);
				if (ret < 0) {
					gnutls_assert();
					goto done;
				}

				ret = gnutls_x509_privkey_import_pkcs8
				    (*key, &data, GNUTLS_X509_FMT_DER,
				     password,
				     type ==
				     GNUTLS_BAG_PKCS8_KEY ?
				     GNUTLS_PKCS_PLAIN : 0);
				if (ret < 0) {
					gnutls_assert();
					gnutls_x509_privkey_deinit(*key);
					goto done;
				}

				key_id_size = sizeof(key_id);
				ret =
				    gnutls_x509_privkey_get_key_id(*key, 0,
								   key_id,
								   &key_id_size);
				if (ret < 0) {
					gnutls_assert();
					gnutls_x509_privkey_deinit(*key);
					goto done;
				}

				privkey_ok = 1;	/* break */
				break;
			default:
				break;
			}
		}

		idx++;
		gnutls_pkcs12_bag_deinit(bag);

		if (privkey_ok != 0)	/* private key was found */
			break;
	}

	if (privkey_ok == 0) {	/* no private key */
		gnutls_assert();
		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
	}

	/* now find the corresponding certificate 
	 */
	idx = 0;
	bag = NULL;
	for (;;) {
		int elements_in_bag;
		int i;

		ret = gnutls_pkcs12_bag_init(&bag);
		if (ret < 0) {
			bag = NULL;
			gnutls_assert();
			goto done;
		}

		ret = gnutls_pkcs12_get_bag(p12, idx, bag);
		if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
			break;
		if (ret < 0) {
			gnutls_assert();
			goto done;
		}

		ret = gnutls_pkcs12_bag_get_type(bag, 0);
		if (ret < 0) {
			gnutls_assert();
			goto done;
		}

		if (ret == GNUTLS_BAG_ENCRYPTED) {
			ret = gnutls_pkcs12_bag_decrypt(bag, password);
			if (ret < 0) {
				gnutls_assert();
				goto done;
			}
		}

		elements_in_bag = gnutls_pkcs12_bag_get_count(bag);
		if (elements_in_bag < 0) {
			gnutls_assert();
			goto done;
		}

		for (i = 0; i < elements_in_bag; i++) {
			int type;
			gnutls_datum_t data;
			gnutls_x509_crt_t this_cert;

			type = gnutls_pkcs12_bag_get_type(bag, i);
			if (type < 0) {
				gnutls_assert();
				goto done;
			}

			ret = gnutls_pkcs12_bag_get_data(bag, i, &data);
			if (ret < 0) {
				gnutls_assert();
				goto done;
			}

			switch (type) {
			case GNUTLS_BAG_CERTIFICATE:
				ret = gnutls_x509_crt_init(&this_cert);
				if (ret < 0) {
					gnutls_assert();
					goto done;
				}

				ret =
				    gnutls_x509_crt_import(this_cert,
							   &data,
							   GNUTLS_X509_FMT_DER);
				if (ret < 0) {
					gnutls_assert();
					gnutls_x509_crt_deinit(this_cert);
					goto done;
				}

				/* check if the key id match */
				cert_id_size = sizeof(cert_id);
				ret =
				    gnutls_x509_crt_get_key_id(this_cert,
							       0, cert_id,
							       &cert_id_size);
				if (ret < 0) {
					gnutls_assert();
					gnutls_x509_crt_deinit(this_cert);
					goto done;
				}

				if (memcmp(cert_id, key_id, cert_id_size) != 0) {	/* they don't match - skip the certificate */
					if (extra_certs) {
						_extra_certs =
						    gnutls_realloc_fast
						    (_extra_certs,
						     sizeof(_extra_certs
							    [0]) *
						     ++_extra_certs_len);
						if (!_extra_certs) {
							gnutls_assert();
							ret =
							    GNUTLS_E_MEMORY_ERROR;
							goto done;
						}
						_extra_certs
						    [_extra_certs_len -
						     1] = this_cert;
						this_cert = NULL;
					} else {
						gnutls_x509_crt_deinit
						    (this_cert);
					}
				} else {
					if (chain && _chain_len == 0) {
						_chain =
						    gnutls_malloc(sizeof
								  (_chain
								   [0]) *
								  (++_chain_len));
						if (!_chain) {
							gnutls_assert();
							ret =
							    GNUTLS_E_MEMORY_ERROR;
							goto done;
						}
						_chain[_chain_len - 1] =
						    this_cert;
						this_cert = NULL;
					} else {
						gnutls_x509_crt_deinit
						    (this_cert);
					}
				}
				break;

			case GNUTLS_BAG_CRL:
				if (crl == NULL || *crl != NULL) {
					gnutls_assert();
					break;
				}

				ret = gnutls_x509_crl_init(crl);
				if (ret < 0) {
					gnutls_assert();
					goto done;
				}

				ret =
				    gnutls_x509_crl_import(*crl, &data,
							   GNUTLS_X509_FMT_DER);
				if (ret < 0) {
					gnutls_assert();
					gnutls_x509_crl_deinit(*crl);
					goto done;
				}
				break;

			case GNUTLS_BAG_ENCRYPTED:
				/* XXX Bother to recurse one level down?  Unlikely to
				   use the same password anyway. */
			case GNUTLS_BAG_EMPTY:
			default:
				break;
			}
		}

		idx++;
		gnutls_pkcs12_bag_deinit(bag);
	}

	if (chain != NULL) {
		if (_chain_len != 1) {
			ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
			goto done;
		}

		ret =
		    make_chain(&_chain, &_chain_len, &_extra_certs,
			       &_extra_certs_len, flags);
		if (ret < 0) {
			gnutls_assert();
			goto done;
		}
	}

	ret = 0;

      done:
	if (bag)
		gnutls_pkcs12_bag_deinit(bag);

	if (ret < 0) {
		if (*key)
			gnutls_x509_privkey_deinit(*key);
		if (_extra_certs_len && _extra_certs != NULL) {
			for (i = 0; i < _extra_certs_len; i++)
				gnutls_x509_crt_deinit(_extra_certs[i]);
			gnutls_free(_extra_certs);
		}
		if (_chain_len && _chain != NULL) {
			for (i = 0; i < _chain_len; i++)
				gnutls_x509_crt_deinit(_chain[i]);
			gnutls_free(_chain);
		}

		return ret;
	}

	if (extra_certs && _extra_certs_len > 0) {
		*extra_certs = _extra_certs;
		*extra_certs_len = _extra_certs_len;
	} else {
		if (extra_certs) {
			*extra_certs = NULL;
			*extra_certs_len = 0;
		}
		for (i = 0; i < _extra_certs_len; i++)
			gnutls_x509_crt_deinit(_extra_certs[i]);
		gnutls_free(_extra_certs);
	}

	if (chain != NULL) {
		*chain = _chain;
		*chain_len = _chain_len;
	}

	return ret;
}
示例#8
0
文件: common.c 项目: ares89/vlc
static void
print_dh_info (gnutls_session_t session, const char *str)
{
  printf ("- %sDiffie-Hellman parameters\n", str);
  printf (" - Using prime: %d bits\n", gnutls_dh_get_prime_bits (session));
  printf (" - Secret key: %d bits\n", gnutls_dh_get_secret_bits (session));
  printf (" - Peer's public key: %d bits\n",
          gnutls_dh_get_peers_public_bits (session));

  if (print_cert)
    {
      int ret;
      gnutls_datum_t raw_gen = { NULL, 0 };
      gnutls_datum_t raw_prime = { NULL, 0 };
      gnutls_dh_params_t dh_params = NULL;
      unsigned char *params_data = NULL;
      size_t params_data_size = 0;

      ret = gnutls_dh_get_group (session, &raw_gen, &raw_prime);
      if (ret)
        {
          fprintf (stderr, "gnutls_dh_get_group %d\n", ret);
          goto out;
        }

      ret = gnutls_dh_params_init (&dh_params);
      if (ret)
        {
          fprintf (stderr, "gnutls_dh_params_init %d\n", ret);
          goto out;
        }

      ret = gnutls_dh_params_import_raw (dh_params, &raw_prime, &raw_gen);
      if (ret)
        {
          fprintf (stderr, "gnutls_dh_params_import_raw %d\n", ret);
          goto out;
        }

      ret = gnutls_dh_params_export_pkcs3 (dh_params,
                                           GNUTLS_X509_FMT_PEM,
                                           params_data, &params_data_size);
      if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
        {
          fprintf (stderr, "gnutls_dh_params_export_pkcs3 %d\n", ret);
          goto out;
        }

      params_data = gnutls_malloc (params_data_size);
      if (!params_data)
        {
          fprintf (stderr, "gnutls_malloc %d\n", ret);
          goto out;
        }

      ret = gnutls_dh_params_export_pkcs3 (dh_params,
                                           GNUTLS_X509_FMT_PEM,
                                           params_data, &params_data_size);
      if (ret)
        {
          fprintf (stderr, "gnutls_dh_params_export_pkcs3-2 %d\n", ret);
          goto out;
        }

      printf (" - PKCS#3 format:\n\n%.*s\n", (int) params_data_size,
              params_data);

    out:
      gnutls_free (params_data);
      gnutls_free (raw_prime.data);
      gnutls_free (raw_gen.data);
      gnutls_dh_params_deinit (dh_params);
    }
}
示例#9
0
文件: common.c 项目: ares89/vlc
static void
print_x509_info (gnutls_session_t session, const char *hostname, int insecure)
{
  gnutls_x509_crt_t crt;
  const gnutls_datum_t *cert_list;
  unsigned int cert_list_size = 0, j;
  int hostname_ok = 0;
  int ret;

  cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
  if (cert_list_size == 0)
    {
      fprintf (stderr, "No certificates found!\n");
      return;
    }

  printf (" - Got a certificate list of %d certificates.\n", cert_list_size);

  for (j = 0; j < cert_list_size; j++)
    {
      gnutls_datum_t cinfo;

      gnutls_x509_crt_init (&crt);
      ret = gnutls_x509_crt_import (crt, &cert_list[j], GNUTLS_X509_FMT_DER);
      if (ret < 0)
        {
          fprintf (stderr, "Decoding error: %s\n", gnutls_strerror (ret));
          return;
        }

      printf (" - Certificate[%d] info:\n  - ", j);

      if (verbose)
        ret = gnutls_x509_crt_print (crt, GNUTLS_CRT_PRINT_FULL, &cinfo);
      else
        ret = gnutls_x509_crt_print (crt, GNUTLS_CRT_PRINT_ONELINE, &cinfo);
      if (ret == 0)
        {
          printf ("%s\n", cinfo.data);
          gnutls_free (cinfo.data);
        }

      if (print_cert)
        {
          size_t size = 0;
          char *p = NULL;

          ret = gnutls_x509_crt_export (crt, GNUTLS_X509_FMT_PEM, p, &size);
          if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
            {
              p = malloc (size);
              if (!p)
                {
                  fprintf (stderr, "gnutls_malloc\n");
                  exit (1);
                }

              ret = gnutls_x509_crt_export (crt, GNUTLS_X509_FMT_PEM,
                                            p, &size);
            }
          if (ret < 0)
            {
              fprintf (stderr, "Encoding error: %s\n", gnutls_strerror (ret));
              return;
            }

          fputs ("\n", stdout);
          fputs (p, stdout);
          fputs ("\n", stdout);

          gnutls_free (p);
        }

      if (j == 0 && hostname != NULL)
        {
          /* Check the hostname of the first certificate if it matches
           * the name of the host we connected to.
           */
          if (gnutls_x509_crt_check_hostname (crt, hostname) == 0)
            hostname_ok = 1;
          else
            hostname_ok = 2;
        }

      gnutls_x509_crt_deinit (crt);
    }

  if (hostname_ok == 1)
    {
      printf ("- The hostname in the certificate does NOT match '%s'\n",
              hostname);
      if (!insecure)
        exit (1);
    }
  else if (hostname_ok == 2)
    {
      printf ("- The hostname in the certificate matches '%s'.\n", hostname);
    }
}
示例#10
0
/* Run an HMAC using the key above on the library binary data. 
 * Returns true on success and false on error.
 */
static unsigned check_binary_integrity(const char* libname, const char* symbol)
{
	int ret;
	unsigned prev;
	char mac_file[GNUTLS_PATH_MAX];
	char file[GNUTLS_PATH_MAX];
	uint8_t hmac[HMAC_SIZE];
	uint8_t new_hmac[HMAC_SIZE];
	size_t hmac_size;
	gnutls_datum_t data;

	ret = get_library_path(libname, symbol, file, sizeof(file));
	if (ret < 0) {
		_gnutls_debug_log("Could not get path for library %s\n", libname);
		return 0;
	}

	_gnutls_debug_log("Loading: %s\n", file);
	ret = gnutls_load_file(file, &data);
	if (ret < 0) {
		_gnutls_debug_log("Could not load: %s\n", file);
		return gnutls_assert_val(0);
	}

	prev = _gnutls_get_lib_state();
	_gnutls_switch_lib_state(LIB_STATE_OPERATIONAL);
	ret = gnutls_hmac_fast(HMAC_ALGO, FIPS_KEY, sizeof(FIPS_KEY)-1,
		data.data, data.size, new_hmac);
	_gnutls_switch_lib_state(prev);
	
	gnutls_free(data.data);

	if (ret < 0)
		return gnutls_assert_val(0);

	/* now open the .hmac file and compare */
	get_hmac_file(mac_file, sizeof(mac_file), file);

	ret = gnutls_load_file(mac_file, &data);
	if (ret < 0) {
		get_hmac_file2(mac_file, sizeof(mac_file), file);
		ret = gnutls_load_file(mac_file, &data);
		if (ret < 0) {
			_gnutls_debug_log("Could not open %s for MAC testing: %s\n", mac_file, gnutls_strerror(ret));
			return gnutls_assert_val(0);
		}
	}

	hmac_size = hex_data_size(data.size);
	ret = gnutls_hex_decode(&data, hmac, &hmac_size);
	gnutls_free(data.data);

	if (ret < 0) {
		_gnutls_debug_log("Could not convert hex data to binary for MAC testing for %s.\n", libname);
		return gnutls_assert_val(0);
	}

	if (hmac_size != sizeof(hmac) ||
			memcmp(hmac, new_hmac, sizeof(hmac)) != 0) {
		_gnutls_debug_log("Calculated MAC for %s does not match\n", libname);
		return gnutls_assert_val(0);
	}
	_gnutls_debug_log("Successfully verified MAC for %s (%s)\n", mac_file, libname);
	
	return 1;
}
示例#11
0
文件: common.c 项目: ares89/vlc
static void
print_openpgp_info (gnutls_session_t session, const char *hostname,
                    int insecure)
{

  gnutls_openpgp_crt_t crt;
  const gnutls_datum_t *cert_list;
  int cert_list_size = 0;
  int hostname_ok = 0;
  int ret;

  cert_list = gnutls_certificate_get_peers (session, &cert_list_size);

  if (cert_list_size > 0)
    {
      gnutls_datum_t cinfo;

      gnutls_openpgp_crt_init (&crt);
      ret = gnutls_openpgp_crt_import (crt, &cert_list[0],
                                       GNUTLS_OPENPGP_FMT_RAW);
      if (ret < 0)
        {
          fprintf (stderr, "Decoding error: %s\n", gnutls_strerror (ret));
          return;
        }

      if (verbose)
        ret = gnutls_openpgp_crt_print (crt, GNUTLS_CRT_PRINT_FULL, &cinfo);
      else
        ret =
          gnutls_openpgp_crt_print (crt, GNUTLS_CRT_PRINT_ONELINE, &cinfo);
      if (ret == 0)
        {
          printf (" - %s\n", cinfo.data);
          gnutls_free (cinfo.data);
        }

      if (print_cert)
        {
          size_t size = 0;
          char *p = NULL;

          ret = gnutls_openpgp_crt_export (crt, GNUTLS_OPENPGP_FMT_BASE64,
                                           p, &size);
          if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
            {
              p = malloc (size);
              if (!p)
                {
                  fprintf (stderr, "gnutls_malloc\n");
                  exit (1);
                }

              ret = gnutls_openpgp_crt_export (crt, GNUTLS_OPENPGP_FMT_BASE64,
                                               p, &size);
            }
          if (ret < 0)
            {
              fprintf (stderr, "Encoding error: %s\n", gnutls_strerror (ret));
              return;
            }

          fputs (p, stdout);
          fputs ("\n", stdout);

          gnutls_free (p);
        }

      if (hostname != NULL)
        {
          /* Check the hostname of the first certificate if it matches
           * the name of the host we connected to.
           */
          if (gnutls_openpgp_crt_check_hostname (crt, hostname) == 0)
            hostname_ok = 1;
          else
            hostname_ok = 2;
        }

      gnutls_openpgp_crt_deinit (crt);
    }

  if (hostname_ok == 1)
    {
      printf ("- The hostname in the certificate does NOT match '%s'\n",
              hostname);
      if (!insecure)
        exit (1);
    }
  else if (hostname_ok == 2)
    {
      printf ("- The hostname in the certificate matches '%s'.\n", hostname);
    }
}
示例#12
0
/* Loads a x509 private key list
 */
gnutls_x509_privkey_t *load_privkey_list(int mand, size_t * privkey_size,
					 common_info_st * info)
{
	static gnutls_x509_privkey_t key[MAX_KEYS];
	char *ptr;
	int ret, i;
	gnutls_datum_t dat, file_data;
	int ptr_size;
	unsigned int flags = 0;
	const char *pass;

	*privkey_size = 0;
	fprintf(stderr, "Loading private key list...\n");

	if (info->privkey == NULL) {
		if (mand) {
			fprintf(stderr, "missing --load-privkey");
			exit(1);
		} else
			return NULL;
	}

	ret = gnutls_load_file(info->privkey, &file_data);
	if (ret < 0) {
		fprintf(stderr, "%s", info->privkey);
		exit(1);
	}

	ptr = (void *) file_data.data;
	ptr_size = file_data.size;

	for (i = 0; i < MAX_KEYS; i++) {
		ret = gnutls_x509_privkey_init(&key[i]);
		if (ret < 0) {
			fprintf(stderr, "privkey_init: %s",
				gnutls_strerror(ret));
			exit(1);
		}

		dat.data = (void *) ptr;
		dat.size = ptr_size;

		ret =
		    gnutls_x509_privkey_import2(key[i], &dat,
						info->incert_format, NULL,
						0);
		if (ret == GNUTLS_E_DECRYPTION_FAILED) {
			pass = get_password(info, &flags, 0);
			ret =
			    gnutls_x509_privkey_import2(key[i], &dat,
							info->
							incert_format,
							pass, flags);
		}

		if (ret < 0 && *privkey_size > 0)
			break;
		if (ret < 0) {
			fprintf(stderr, "privkey_import: %s",
				gnutls_strerror(ret));
			exit(1);
		}

		(*privkey_size)++;

		if (info->incert_format != GNUTLS_X509_FMT_PEM)
			break;

		ptr = strstr(ptr, "---END");
		if (ptr == NULL)
			break;
		ptr++;

		ptr_size = file_data.size;
		ptr_size -=
		    (unsigned int) ((unsigned char *) ptr -
				    (unsigned char *) buffer);

		if (ptr_size < 0)
			break;

	}

	gnutls_free(file_data.data);
	fprintf(stderr, "Loaded %d private keys.\n", (int) *privkey_size);

	return key;
}
示例#13
0
/* This function behaves exactly like write(). The only difference is
 * that it accepts, the gnutls_session_t and the content_type_t of data to
 * send (if called by the user the Content is specific)
 * It is intended to transfer data, under the current session.    
 *
 * Oct 30 2001: Removed capability to send data more than MAX_RECORD_SIZE.
 * This makes the function much easier to read, and more error resistant
 * (there were cases were the old function could mess everything up).
 * --nmav
 *
 * This function may accept a NULL pointer for data, and 0 for size, if
 * and only if the previous send was interrupted for some reason.
 *
 */
ssize_t
_gnutls_send_int (gnutls_session_t session, content_type_t type,
		  gnutls_handshake_description_t htype, const void *_data,
		  size_t sizeofdata)
{
  uint8_t *cipher;
  int cipher_size;
  int retval, ret;
  int data2send_size;
  uint8_t headers[5];
  const uint8_t *data = _data;
  int erecord_size = 0;
  opaque *erecord = NULL;

  /* Do not allow null pointer if the send buffer is empty.
   * If the previous send was interrupted then a null pointer is
   * ok, and means to resume.
   */
  if (session->internals.record_send_buffer.length == 0 &&
      (sizeofdata == 0 && _data == NULL))
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if (type != GNUTLS_ALERT)	/* alert messages are sent anyway */
    if (session_is_valid (session) || session->internals.may_not_write != 0)
      {
	gnutls_assert ();
	return GNUTLS_E_INVALID_SESSION;
      }



  headers[0] = type;

  /* Use the default record version, if it is
   * set.
   */
  copy_record_version (session, htype, &headers[1]);


  _gnutls_record_log
    ("REC[%x]: Sending Packet[%d] %s(%d) with length: %d\n", session,
     (int) _gnutls_uint64touint32 (&session->connection_state.
				   write_sequence_number),
     _gnutls_packet2str (type), type, sizeofdata);

  if (sizeofdata > MAX_RECORD_SEND_SIZE)
    data2send_size = MAX_RECORD_SEND_SIZE;
  else
    data2send_size = sizeofdata;

  /* Only encrypt if we don't have data to send 
   * from the previous run. - probably interrupted.
   */
  if (session->internals.record_send_buffer.length > 0)
    {
      ret = _gnutls_io_write_flush (session);
      if (ret > 0)
	cipher_size = ret;
      else
	cipher_size = 0;

      cipher = NULL;

      retval = session->internals.record_send_buffer_user_size;
    }
  else
    {

      /* now proceed to packet encryption
       */
      cipher_size = data2send_size + MAX_RECORD_OVERHEAD;
      cipher = gnutls_malloc (cipher_size);
      if (cipher == NULL)
	{
	  gnutls_assert ();
	  return GNUTLS_E_MEMORY_ERROR;
	}

      cipher_size =
	_gnutls_encrypt (session, headers, RECORD_HEADER_SIZE, data,
			 data2send_size, cipher, cipher_size, type, 1);
      if (cipher_size <= 0)
	{
	  gnutls_assert ();
	  if (cipher_size == 0)
	    cipher_size = GNUTLS_E_ENCRYPTION_FAILED;
	  gnutls_afree (erecord);
	  gnutls_free (cipher);
	  return cipher_size;	/* error */
	}

      retval = data2send_size;
      session->internals.record_send_buffer_user_size = data2send_size;

      /* increase sequence number
       */
      if (_gnutls_uint64pp
	  (&session->connection_state.write_sequence_number) != 0)
	{
	  session_invalidate (session);
	  gnutls_assert ();
	  gnutls_afree (erecord);
	  gnutls_free (cipher);
	  return GNUTLS_E_RECORD_LIMIT_REACHED;
	}

      ret =
	_gnutls_io_write_buffered2 (session, erecord, erecord_size,
				    cipher, cipher_size);
      gnutls_afree (erecord);
      gnutls_free (cipher);
    }

  if (ret != cipher_size + erecord_size)
    {
      if (ret < 0 && gnutls_error_is_fatal (ret) == 0)
	{
	  /* If we have sent any data then just return
	   * the error value. Do not invalidate the session.
	   */
	  gnutls_assert ();
	  return ret;
	}

      if (ret > 0)
	{
	  gnutls_assert ();
	  ret = GNUTLS_E_INTERNAL_ERROR;
	}
      session_unresumable (session);
      session->internals.may_not_write = 1;
      gnutls_assert ();
      return ret;
    }

  session->internals.record_send_buffer_user_size = 0;

  _gnutls_record_log ("REC[%x]: Sent Packet[%d] %s(%d) with length: %d\n",
		      session,
		      (int) _gnutls_uint64touint32 (&session->
						    connection_state.
						    write_sequence_number),
		      _gnutls_packet2str (type), type, cipher_size);

  return retval;
}
示例#14
0
static void
client (int sds[], struct params_res *params)
{
  int ret, ii;
  gnutls_session_t session;
  char buffer[MAX_BUF + 1];
  gnutls_anon_client_credentials_t anoncred;
  /* Need to enable anonymous KX specifically. */

  /* variables used in session resuming
   */
  int t;
  gnutls_datum_t session_data;

  if (debug)
    {
      gnutls_global_set_log_function (tls_log_func);
      gnutls_global_set_log_level (2);
    }
  global_init ();

  gnutls_anon_allocate_client_credentials (&anoncred);

  for (t = 0; t < SESSIONS; t++)
    {
      int sd = sds[t];

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

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

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

      if (params->enable_session_ticket_client)
        gnutls_session_ticket_enable_client (session);

      if (t > 0)
        {
          /* if this is not the first time we connect */
          gnutls_session_set_data (session, session_data.data,
                                   session_data.size);
          gnutls_free (session_data.data);
        }

      gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);

      /* Perform the TLS handshake
       */
      ret = gnutls_handshake (session);

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

      if (t == 0)
        {                       /* the first time we connect */
          /* get the session data size */
          ret = gnutls_session_get_data2 (session, &session_data);
          if (ret < 0)
            fail ("Getting resume data failed\n");
        }
      else
        {                       /* the second time we connect */

          /* check if we actually resumed the previous session */
          if (gnutls_session_is_resumed (session) != 0)
            {
              if (params->expect_resume)
                {
                  if (debug)
                    success ("- Previous session was resumed\n");
                }
              else
                fail ("- Previous session was resumed\n");
            }
          else
            {
              if (params->expect_resume)
                {
                  fail ("*** Previous session was NOT resumed\n");
                }
              else
                {
                  if (debug)
                    success
                      ("*** Previous session was NOT resumed (expected)\n");
                }
            }
        }

      gnutls_record_send (session, MSG, strlen (MSG));

      ret = gnutls_record_recv (session, buffer, MAX_BUF);
      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));
          goto end;
        }

      if (debug )
        {
          printf ("- Received %d bytes: ", ret);
          for (ii = 0; ii < ret; ii++)
            {
              fputc (buffer[ii], stdout);
            }
          fputs ("\n", stdout);
        }

      gnutls_bye (session, GNUTLS_SHUT_RDWR);

      close (sd);

      gnutls_deinit (session);
    }

end:
  gnutls_anon_free_client_credentials (anoncred);
}
示例#15
0
static
int get_win_urls(const CERT_CONTEXT *cert, char **cert_url, char **key_url,
		 char **label, gnutls_datum_t *der)
{
	BOOL r;
	int ret;
	DWORD tl_size;
	gnutls_datum_t tmp_label = {NULL, 0};
	char name[MAX_CN*2];
	char hex[MAX_WID_SIZE*2+1];
	gnutls_buffer_st str;
#ifdef WORDS_BIGENDIAN
	const unsigned bigendian = 1;
#else
	const unsigned bigendian = 0;
#endif

	if (cert == NULL)
		return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);

	if (der) {
		der->data = gnutls_malloc(cert->cbCertEncoded);
		if (der->data == NULL)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		memcpy(der->data, cert->pbCertEncoded, cert->cbCertEncoded);
		der->size = cert->cbCertEncoded;
	}

	_gnutls_buffer_init(&str);
	if (label)
		*label = NULL;
	if (key_url)
		*key_url = NULL;
	if (cert_url)
		*cert_url = NULL;


	tl_size = sizeof(name);
	r = CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID,
					      name, &tl_size);
	if (r != 0) { /* optional */
		ret = _gnutls_ucs2_to_utf8(name, tl_size, &tmp_label, bigendian);
		if (ret < 0) {
			gnutls_assert();
			goto fail;
		}
		if (label)
			*label = (char*)tmp_label.data;
	}

	tl_size = sizeof(name);
	r = CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID,
					      name, &tl_size);
	if (r == 0) {
		gnutls_assert();
		ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
		goto fail;
	}

	if (_gnutls_bin2hex(name, tl_size, hex, sizeof(hex), 0) == NULL) {
		ret = gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
		goto fail;
	}

	ret = _gnutls_buffer_append_printf(&str, WIN_URL"id=%s;type=cert", hex);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	if (tmp_label.data) {
		ret = _gnutls_buffer_append_str(&str, ";name=");
		if (ret < 0) {
			gnutls_assert();
			goto fail;
		}

		ret = _gnutls_buffer_append_escape(&str, tmp_label.data, tmp_label.size, " ");
		if (ret < 0) {
			gnutls_assert();
			goto fail;
		}
	}

	ret = _gnutls_buffer_append_data(&str, "\x00", 1);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	if (cert_url)
		*cert_url = (char*)str.data;
	_gnutls_buffer_init(&str);

	ret = _gnutls_buffer_append_printf(&str, WIN_URL"id=%s;type=privkey", hex);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	if (tmp_label.data) {
		ret = _gnutls_buffer_append_str(&str, ";name=");
		if (ret < 0) {
			gnutls_assert();
			goto fail;
		}

		ret = _gnutls_buffer_append_escape(&str, tmp_label.data, tmp_label.size, " ");
		if (ret < 0) {
			gnutls_assert();
			goto fail;
		}
	}

	ret = _gnutls_buffer_append_data(&str, "\x00", 1);
	if (ret < 0) {
		gnutls_assert();
		goto fail;
	}

	if (key_url)
		*key_url = (char*)str.data;
	_gnutls_buffer_init(&str);

	ret = 0;
	goto cleanup;

 fail:
 	if (der)
	 	gnutls_free(der->data);
 	if (cert_url)
	 	gnutls_free(*cert_url);
 	if (key_url)
	 	gnutls_free(*key_url);
 	if (label)
 		gnutls_free(*label);
 cleanup:
 	_gnutls_buffer_clear(&str);
 	return ret;
}
示例#16
0
/* This function transmits the flight that has been previously
 * buffered.
 *
 * This function is called from the handshake layer and calls the
 * record layer.
 */
int
_dtls_transmit (gnutls_session_t session)
{
int ret;
uint8_t* buf = NULL;
unsigned int timeout;

  /* PREPARING -> SENDING state transition */
  mbuffer_head_st *const send_buffer =
    &session->internals.handshake_send_buffer;
  mbuffer_st *cur;
  gnutls_handshake_description_t last_type = 0;
  unsigned int diff;
  struct timespec now;
  
  gettime(&now);

  /* If we have already sent a flight and we are operating in a 
   * non blocking way, check if it is time to retransmit or just
   * return.
   */
  if (session->internals.dtls.flight_init != 0 && session->internals.dtls.blocking == 0)
    {
      /* just in case previous run was interrupted */
      ret = _gnutls_io_write_flush (session);
      if (ret < 0)
        {
          gnutls_assert();
          goto cleanup;
        }

      if (session->internals.dtls.last_flight == 0 || !_dtls_is_async(session))
        {
          /* check for ACK */
          ret = _gnutls_io_check_recv(session, 0);
          if (ret == GNUTLS_E_TIMEDOUT)
            {
              /* if no retransmission is required yet just return 
               */
              if (_dtls_timespec_sub_ms(&now, &session->internals.dtls.last_retransmit) < TIMER_WINDOW)
                {
                  gnutls_assert();
                  goto nb_timeout;
                }
            }
          else /* received something */
            {
              if (ret == 0)
                {
                  ret = is_next_hpacket_expected(session);
                  if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
                    goto nb_timeout;
                  if (ret < 0 && ret != GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET)
                    {
                      gnutls_assert();
                      goto cleanup;
                    }
                  if (ret == 0) goto end_flight;
                  /* if ret == GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET retransmit */
                }
              else
                goto nb_timeout;
            }
        }
    }

  do 
    {
      timeout = TIMER_WINDOW;

      diff = _dtls_timespec_sub_ms(&now, &session->internals.dtls.handshake_start_time);
      if (diff >= session->internals.dtls.total_timeout_ms) 
        {
          _gnutls_dtls_log("Session timeout: %u ms\n", diff);
          ret = gnutls_assert_val(GNUTLS_E_TIMEDOUT);
          goto end_flight;
        }

      diff = _dtls_timespec_sub_ms(&now, &session->internals.dtls.last_retransmit);
      if (session->internals.dtls.flight_init == 0 || diff >= TIMER_WINDOW)
        {
          _gnutls_dtls_log ("DTLS[%p]: %sStart of flight transmission.\n", session,  (session->internals.dtls.flight_init == 0)?"":"re-");
          for (cur = send_buffer->head;
               cur != NULL; cur = cur->next)
            {
              ret = transmit_message (session, cur, &buf);
              if (ret < 0)
                {
                  gnutls_assert();
                  goto end_flight;
                }

              last_type = cur->htype;
            }
          gettime(&session->internals.dtls.last_retransmit);

          if (session->internals.dtls.flight_init == 0)
            {
              session->internals.dtls.flight_init = 1;
              RESET_TIMER;
              timeout = TIMER_WINDOW;

              if (last_type == GNUTLS_HANDSHAKE_FINISHED)
                {
              /* On the last flight we cannot ensure retransmission
               * from here. _dtls_wait_and_retransmit() is being called
               * by handshake.
               */
                  session->internals.dtls.last_flight = 1;
                }
              else
                session->internals.dtls.last_flight = 0;
            }
          else
            {
              UPDATE_TIMER;
            }
        }

      ret = _gnutls_io_write_flush (session);
      if (ret < 0)
        {
          ret = gnutls_assert_val(ret);
          goto cleanup;
        }

      /* last message in handshake -> no ack */
      if (session->internals.dtls.last_flight != 0)
        {
          /* we don't wait here. We just return 0 and
           * if a retransmission occurs because peer didn't receive it
           * we rely on the record or handshake
           * layer calling this function again.
           */
          ret = 0;
          goto cleanup;
        }
      else /* all other messages -> implicit ack (receive of next flight) */
        {
          if (session->internals.dtls.blocking != 0)
            ret = _gnutls_io_check_recv(session, timeout);
          else
            {
              ret = _gnutls_io_check_recv(session, 0);
              if (ret == GNUTLS_E_TIMEDOUT)
                {
                  goto nb_timeout;
                }
            }
          
          if (ret == 0)
            {
              ret = is_next_hpacket_expected(session);
              if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED)
                goto nb_timeout;

              if (ret == GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET)
                {
                  ret = GNUTLS_E_TIMEDOUT;
                  goto keep_up;
                }
              if (ret < 0)
                {
                  gnutls_assert();
                  goto cleanup;
                }
              goto end_flight;
            }
        }

keep_up:
      gettime(&now);
    } while(ret == GNUTLS_E_TIMEDOUT);

  if (ret < 0)
    {
      ret = gnutls_assert_val(ret);
      goto end_flight;
    }

  ret = 0;

end_flight:
  _gnutls_dtls_log ("DTLS[%p]: End of flight transmission.\n", session);
  _dtls_reset_hsk_state(session);

cleanup:
  if (buf != NULL)
    gnutls_free(buf);

  /* SENDING -> WAITING state transition */
  return ret;

nb_timeout:
  if (buf != NULL)
    gnutls_free(buf);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	ret = 0;

 cleanup:
 	if (p12 != NULL)
 		gnutls_pkcs12_deinit(p12);
 	if (bag1 != NULL)
 		gnutls_pkcs12_bag_deinit(bag1);
 	if (bag2 != NULL)
 		gnutls_pkcs12_bag_deinit(bag2);
 	if (store != NULL)
		CertCloseStore(store, 0);
	gnutls_free(_pfx.data);
	return ret;
}
示例#18
0
int main(void)
{
        int ret, sd, ii;
        gnutls_session_t session;
        char buffer[MAX_BUF + 1];
        const char *err;
        gnutls_psk_client_credentials_t pskcred;
        const gnutls_datum_t key = { (void *) "DEADBEEF", 8 };

        gnutls_global_init();

        gnutls_psk_allocate_client_credentials(&pskcred);
        gnutls_psk_set_client_credentials(pskcred, "test", &key,
                                          GNUTLS_PSK_KEY_HEX);

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

        /* Use default priorities */
        ret =
            gnutls_priority_set_direct(session,
                                       "PERFORMANCE:+ECDHE-PSK:+DHE-PSK:+PSK",
                                       &err);
        if (ret < 0) {
                if (ret == GNUTLS_E_INVALID_REQUEST) {
                        fprintf(stderr, "Syntax error at: %s\n", err);
                }
                exit(1);
        }

        /* put the x509 credentials to the current session
         */
        gnutls_credentials_set(session, GNUTLS_CRD_PSK, pskcred);

        /* connect to the peer
         */
        sd = tcp_connect();

        gnutls_transport_set_int(session, sd);
        gnutls_handshake_set_timeout(session,
                                     GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);

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

        if (ret < 0) {
                fprintf(stderr, "*** Handshake failed\n");
                gnutls_perror(ret);
                goto end;
        } else {
                char *desc;

                desc = gnutls_session_get_desc(session);
                printf("- Session info: %s\n", desc);
                gnutls_free(desc);
        }

        gnutls_record_send(session, MSG, strlen(MSG));

        ret = gnutls_record_recv(session, buffer, MAX_BUF);
        if (ret == 0) {
                printf("- Peer has closed the TLS connection\n");
                goto end;
        } else if (ret < 0 && gnutls_error_is_fatal(ret) == 0) {
                fprintf(stderr, "*** Warning: %s\n", gnutls_strerror(ret));
        } else if (ret < 0) {
                fprintf(stderr, "*** Error: %s\n", gnutls_strerror(ret));
                goto end;
        }

        if (ret > 0) {
                printf("- Received %d bytes: ", ret);
                for (ii = 0; ii < ret; ii++) {
                        fputc(buffer[ii], stdout);
                }
                fputs("\n", stdout);
        }

        gnutls_bye(session, GNUTLS_SHUT_RDWR);

      end:

        tcp_close(sd);

        gnutls_deinit(session);

        gnutls_psk_free_client_credentials(pskcred);

        gnutls_global_deinit();

        return 0;
}
示例#19
0
static int
write_attributes(gnutls_pkcs12_bag_t bag, int elem,
		 ASN1_TYPE c2, const char *where)
{
	int result;
	char root[128];

	/* If the bag attributes are empty, then write
	 * nothing to the attribute field.
	 */
	if (bag->element[elem].friendly_name == NULL &&
	    bag->element[elem].local_key_id.data == NULL) {
		/* no attributes
		 */
		result = asn1_write_value(c2, where, NULL, 0);
		if (result != ASN1_SUCCESS) {
			gnutls_assert();
			return _gnutls_asn2err(result);
		}

		return 0;
	}

	if (bag->element[elem].local_key_id.data != NULL) {

		/* Add a new Attribute
		 */
		result = asn1_write_value(c2, where, "NEW", 1);
		if (result != ASN1_SUCCESS) {
			gnutls_assert();
			return _gnutls_asn2err(result);
		}

		_gnutls_str_cpy(root, sizeof(root), where);
		_gnutls_str_cat(root, sizeof(root), ".?LAST");

		result =
		    _gnutls_x509_encode_and_write_attribute(KEY_ID_OID, c2,
							    root,
							    bag->element
							    [elem].
							    local_key_id.data,
							    bag->element
							    [elem].
							    local_key_id.size,
							    1);
		if (result < 0) {
			gnutls_assert();
			return result;
		}
	}

	if (bag->element[elem].friendly_name != NULL) {
		uint8_t *name;
		int size, i;
		const char *p;

		/* Add a new Attribute
		 */
		result = asn1_write_value(c2, where, "NEW", 1);
		if (result != ASN1_SUCCESS) {
			gnutls_assert();
			return _gnutls_asn2err(result);
		}

		/* convert name to BMPString
		 */
		size = strlen(bag->element[elem].friendly_name) * 2;
		name = gnutls_malloc(size);

		if (name == NULL) {
			gnutls_assert();
			return GNUTLS_E_MEMORY_ERROR;
		}

		p = bag->element[elem].friendly_name;
		for (i = 0; i < size; i += 2) {
			name[i] = 0;
			name[i + 1] = *p;
			p++;
		}

		_gnutls_str_cpy(root, sizeof(root), where);
		_gnutls_str_cat(root, sizeof(root), ".?LAST");

		result =
		    _gnutls_x509_encode_and_write_attribute
		    (FRIENDLY_NAME_OID, c2, root, name, size, 1);

		gnutls_free(name);

		if (result < 0) {
			gnutls_assert();
			return result;
		}
	}

	return 0;
}
示例#20
0
static int pgp_crt_to_raw_pubkey(const gnutls_datum_t * cert,
                                 gnutls_datum_t * rpubkey)
{
#ifdef ENABLE_OPENPGP
    gnutls_openpgp_crt_t crt = NULL;
    gnutls_pubkey_t pubkey = NULL;
    size_t size;
    int ret;

    ret = gnutls_openpgp_crt_init(&crt);
    if (ret < 0)
        return gnutls_assert_val(ret);

    ret = gnutls_pubkey_init(&pubkey);
    if (ret < 0) {
        gnutls_assert();
        goto cleanup;
    }

    ret = gnutls_openpgp_crt_import(crt, cert, GNUTLS_OPENPGP_FMT_RAW);
    if (ret < 0) {
        gnutls_assert();
        goto cleanup;
    }

    ret = gnutls_pubkey_import_openpgp(pubkey, crt, 0);
    if (ret < 0) {
        gnutls_assert();
        goto cleanup;
    }

    size = 0;
    ret =
        gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER, NULL, &size);
    if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
        gnutls_assert();
        goto cleanup;
    }

    rpubkey->data = gnutls_malloc(size);
    if (rpubkey->data == NULL)
        if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
            ret = GNUTLS_E_MEMORY_ERROR;
            gnutls_assert();
            goto cleanup;
        }

    ret =
        gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER,
                             rpubkey->data, &size);
    if (ret < 0) {
        gnutls_free(rpubkey->data);
        gnutls_assert();
        goto cleanup;
    }

    rpubkey->size = size;
    ret = 0;

cleanup:
    gnutls_openpgp_crt_deinit(crt);
    gnutls_pubkey_deinit(pubkey);

    return ret;
#else
    return GNUTLS_E_UNIMPLEMENTED_FEATURE;
#endif
}
示例#21
0
static
void test_sig(gnutls_pk_algorithm_t pk, unsigned hash, unsigned bits)
{
	gnutls_pubkey_t pubkey;
	gnutls_privkey_t privkey;
	gnutls_sign_algorithm_t sign_algo;
	gnutls_datum_t signature;
	const gnutls_datum_t *hash_data;
	int ret;
	unsigned j;

	if (hash == GNUTLS_DIG_SHA1)
		hash_data = &sha1_data;
	else if (hash == GNUTLS_DIG_SHA256)
		hash_data = &sha256_data;
	else
		abort();

	sign_algo =
	    gnutls_pk_to_sign(pk, hash);

	for (j = 0; j < 100; j++) {
		ret = gnutls_pubkey_init(&pubkey);
		if (ret < 0)
			ERR(__LINE__);

		ret = gnutls_privkey_init(&privkey);
		if (ret < 0)
			ERR(__LINE__);

		ret = gnutls_privkey_generate(privkey, pk, bits, 0);
		if (ret < 0)
			ERR(__LINE__);

		ret =
		    gnutls_privkey_sign_hash(privkey, hash,
					     0, hash_data,
					     &signature);
		if (ret < 0)
			ERR(__LINE__);

		ret = gnutls_pubkey_import_privkey(pubkey, privkey, GNUTLS_KEY_DIGITAL_SIGNATURE, 0);
		if (ret < 0)
			ERR(__LINE__);

		ret =
		    gnutls_pubkey_verify_hash2(pubkey,
						sign_algo, 0,
						hash_data, &signature);
		if (ret < 0)
			ERR(__LINE__);

		/* should fail */
		ret =
		    gnutls_pubkey_verify_hash2(pubkey,
						sign_algo, 0,
						&invalid_hash_data,
						&signature);
		if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED)
			ERR(__LINE__);

		sign_algo =
		    gnutls_pk_to_sign(gnutls_pubkey_get_pk_algorithm
				      (pubkey, NULL), hash);

		ret =
		    gnutls_pubkey_verify_hash2(pubkey, sign_algo, 0,
						hash_data, &signature);
		if (ret < 0)
			ERR(__LINE__);

		/* should fail */
		ret =
		    gnutls_pubkey_verify_hash2(pubkey, sign_algo, 0,
						&invalid_hash_data,
						&signature);
		if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED)
			ERR(__LINE__);

		/* test the raw interface */
		gnutls_free(signature.data);
		signature.data = NULL;

		if (pk == GNUTLS_PK_RSA) {
			ret =
			    gnutls_privkey_sign_hash(privkey,
						     hash,
						     GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA,
						     hash_data,
						     &signature);
			if (ret < 0)
				ERR(__LINE__);

			sign_algo =
			    gnutls_pk_to_sign
			    (gnutls_pubkey_get_pk_algorithm
			     (pubkey, NULL), hash);

			ret =
			    gnutls_pubkey_verify_hash2(pubkey,
							sign_algo,
							GNUTLS_PUBKEY_VERIFY_FLAG_TLS1_RSA,
							hash_data,
							&signature);
			if (ret < 0)
				ERR(__LINE__);

		}
		gnutls_free(signature.data);
		gnutls_privkey_deinit(privkey);
		gnutls_pubkey_deinit(pubkey);
	}

}
示例#22
0
/**
 * gnutls_tdb_deinit:
 * @tdb: The structure to be deinitialized
 *
 * This function will deinitialize a public key trust storage structure.
 **/
void gnutls_tdb_deinit(gnutls_tdb_t tdb)
{
    gnutls_free(tdb);
}
示例#23
0
int TLSTransaction::verify_certificate () const
{
  if (_trust == TLSServer::allow_all)
    return 0;

  // This verification function uses the trusted CAs in the credentials
  // structure. So you must have installed one or more CA certificates.
  unsigned int status = 0;
#if GNUTLS_VERSION_NUMBER >= 0x030104
  int ret = gnutls_certificate_verify_peers3 (_session, NULL, &status);
  if (ret < 0)
  {
    if (_debug)
      std::cout << "s: ERROR Certificate verification peers3 failed. " << gnutls_strerror (ret) << "\n";
    return GNUTLS_E_CERTIFICATE_ERROR;
  }
#else
  int ret = gnutls_certificate_verify_peers2 (_session, &status);
  if (ret < 0)
  {
    if (_debug)
      std::cout << "s: ERROR Certificate verification peers2 failed. " << gnutls_strerror (ret) << "\n";
    return GNUTLS_E_CERTIFICATE_ERROR;
  }

  if (status == 0)
  {
    if (gnutls_certificate_type_get (_session) == GNUTLS_CRT_X509)
    {
      const gnutls_datum* cert_list;
      unsigned int cert_list_size;
      gnutls_x509_crt cert;

      cert_list = gnutls_certificate_get_peers (_session, &cert_list_size);
      if (cert_list_size == 0)
      {
        if (_debug)
          std::cout << "s: ERROR Certificate get peers failed. " << gnutls_strerror (ret) << "\n";
        return GNUTLS_E_CERTIFICATE_ERROR;
      }

      ret = gnutls_x509_crt_init (&cert);
      if (ret < 0)
      {
        if (_debug)
          std::cout << "s: ERROR x509 init failed. " << gnutls_strerror (ret) << "\n";
        return GNUTLS_E_CERTIFICATE_ERROR;
      }

      ret = gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER);
      if (ret < 0)
      {
        if (_debug)
          std::cout << "s: ERROR x509 cert import. " << gnutls_strerror (ret) << "\n";
        gnutls_x509_crt_deinit(cert);
        status = GNUTLS_E_CERTIFICATE_ERROR;
      }
    }
    else
      return GNUTLS_E_CERTIFICATE_ERROR;
  }
#endif
  if (ret < 0)
    return GNUTLS_E_CERTIFICATE_ERROR;

#if GNUTLS_VERSION_NUMBER >= 0x030105
  gnutls_certificate_type_t type = gnutls_certificate_type_get (_session);
  gnutls_datum_t out;
  ret = gnutls_certificate_verification_status_print (status, type, &out, 0);
  if (ret < 0)
  {
    if (_debug)
      std::cout << "s: ERROR certificate verification status. " << gnutls_strerror (ret) << "\n";
    return GNUTLS_E_CERTIFICATE_ERROR;
  }

  gnutls_free (out.data);
#endif

  if (status != 0)
    return GNUTLS_E_CERTIFICATE_ERROR;

  // Continue handshake.
  return 0;
}
示例#24
0
文件: gnutls_mpi.c 项目: ares89/vlc
bigint_t
_gnutls_mpi_randomize (bigint_t r, unsigned int bits,
                       gnutls_rnd_level_t level)
{
  size_t size = 1 + (bits / 8);
  int ret;
  int rem, i;
  bigint_t tmp;
  char tmpbuf[512];
  opaque *buf;
  int buf_release = 0;

  if (size < sizeof (tmpbuf))
    {
      buf = tmpbuf;
    }
  else
    {
      buf = gnutls_malloc (size);
      if (buf == NULL)
        {
          gnutls_assert ();
          goto cleanup;
        }
      buf_release = 1;
    }


  ret = _gnutls_rnd (level, buf, size);
  if (ret < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  /* mask the bits that weren't requested */
  rem = bits % 8;

  if (rem == 0)
    {
      buf[0] = 0;
    }
  else
    {
      for (i = 8; i >= rem; i--)
        buf[0] = clearbit (buf[0], i);
    }

  ret = _gnutls_mpi_scan (&tmp, buf, size);
  if (ret < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  if (buf_release != 0)
    {
      gnutls_free (buf);
      buf = NULL;
    }

  if (r != NULL)
    {
      _gnutls_mpi_set (r, tmp);
      _gnutls_mpi_release (&tmp);
      return r;
    }

  return tmp;

cleanup:
  if (buf_release != 0)
    gnutls_free (buf);
  return NULL;
}
示例#25
0
void _gnutls_mpi_log(const char *prefix, bigint_t a)
{
	size_t binlen = 0;
	void *binbuf;
	size_t hexlen;
	char *hexbuf;
	int res;

	if (_gnutls_log_level < 2)
		return;

	res = _gnutls_mpi_print(a, NULL, &binlen);
	if (res < 0 && res != GNUTLS_E_SHORT_MEMORY_BUFFER) {
		gnutls_assert();
		_gnutls_hard_log("MPI: %s can't print value (%d/%d)\n",
				 prefix, res, (int) binlen);
		return;
	}

	if (binlen > 1024 * 1024) {
		gnutls_assert();
		_gnutls_hard_log("MPI: %s too large mpi (%d)\n", prefix,
				 (int) binlen);
		return;
	}

	binbuf = gnutls_malloc(binlen);
	if (!binbuf) {
		gnutls_assert();
		_gnutls_hard_log("MPI: %s out of memory (%d)\n", prefix,
				 (int) binlen);
		return;
	}

	res = _gnutls_mpi_print(a, binbuf, &binlen);
	if (res != 0) {
		gnutls_assert();
		_gnutls_hard_log("MPI: %s can't print value (%d/%d)\n",
				 prefix, res, (int) binlen);
		gnutls_free(binbuf);
		return;
	}

	hexlen = 2 * binlen + 1;
	hexbuf = gnutls_malloc(hexlen);

	if (!hexbuf) {
		gnutls_assert();
		_gnutls_hard_log("MPI: %s out of memory (hex %d)\n",
				 prefix, (int) hexlen);
		gnutls_free(binbuf);
		return;
	}

	_gnutls_bin2hex(binbuf, binlen, hexbuf, hexlen, NULL);

	_gnutls_hard_log("MPI: length: %d\n\t%s%s\n", (int) binlen, prefix,
			 hexbuf);

	gnutls_free(hexbuf);
	gnutls_free(binbuf);
}
示例#26
0
static
int cng_sign(gnutls_privkey_t key, void *userdata,
	     const gnutls_datum_t *raw_data,
	     gnutls_datum_t *signature)
{
	priv_st *priv = userdata;
	BCRYPT_PKCS1_PADDING_INFO _info;
	void *info = NULL;
	DWORD ret_sig = 0;
	int ret;
	DWORD flags = 0;
	gnutls_datum_t data = {raw_data->data, raw_data->size};
	uint8_t digest[MAX_HASH_SIZE];
	unsigned int digest_size;
	gnutls_digest_algorithm_t algo;
	SECURITY_STATUS r;

	signature->data = NULL;
	signature->size = 0;

	if (priv->pk == GNUTLS_PK_RSA) {

		flags = BCRYPT_PAD_PKCS1;
		info = &_info;

		if (raw_data->size == 36) { /* TLS 1.0 MD5+SHA1 */
			_info.pszAlgId = NULL;
		} else {
			digest_size = sizeof(digest);
			ret = decode_ber_digest_info(raw_data, &algo, digest, &digest_size);
			if (ret < 0)
				return gnutls_assert_val(ret);

			switch(algo) {
				case GNUTLS_DIG_SHA1:
					_info.pszAlgId = NCRYPT_SHA1_ALGORITHM;
					break;
#ifdef NCRYPT_SHA224_ALGORITHM
				case GNUTLS_DIG_SHA224:
					_info.pszAlgId = NCRYPT_SHA224_ALGORITHM;
					break;
#endif
				case GNUTLS_DIG_SHA256:
					_info.pszAlgId = NCRYPT_SHA256_ALGORITHM;
					break;
				case GNUTLS_DIG_SHA384:
					_info.pszAlgId = NCRYPT_SHA384_ALGORITHM;
					break;
				case GNUTLS_DIG_SHA512:
					_info.pszAlgId = NCRYPT_SHA512_ALGORITHM;
					break;
				default:
					return gnutls_assert_val(GNUTLS_E_UNKNOWN_HASH_ALGORITHM);
			}
			data.data = digest;
			data.size = digest_size;
		}
	}

	r = pNCryptSignHash(priv->nc, info, data.data, data.size,
			   NULL, 0,
			   &ret_sig, flags);
	if (FAILED(r)) {
		gnutls_assert();
		_gnutls_debug_log("error in pre-signing: %d\n", (int)GetLastError());
		ret = GNUTLS_E_PK_SIGN_FAILED;
		goto fail;
	}

	signature->size = ret_sig;
	signature->data = gnutls_malloc(signature->size);
	if (signature->data == NULL)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	r = pNCryptSignHash(priv->nc, info, data.data, data.size,
			   signature->data, signature->size,
			   &ret_sig, flags);
	if (FAILED(r)) {
		gnutls_assert();
		_gnutls_debug_log("error in signing: %d\n", (int)GetLastError());
		ret = GNUTLS_E_PK_SIGN_FAILED;
		goto fail;
	}

	signature->size = ret_sig;

	return 0;
 fail:
	gnutls_free(signature->data);
	return ret;
}
示例#27
0
static int
wrap_nettle_cipher_init (gnutls_cipher_algorithm_t algo, void **_ctx, int enc)
{
  struct nettle_cipher_ctx *ctx;

  ctx = gnutls_calloc (1, sizeof (*ctx));
  if (ctx == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  ctx->algo = algo;
  ctx->enc = enc;

  switch (algo)
    {
    case GNUTLS_CIPHER_AES_128_GCM:
    case GNUTLS_CIPHER_AES_256_GCM:
      ctx->encrypt = _gcm_encrypt;
      ctx->decrypt = _gcm_decrypt;
      ctx->i_encrypt = (nettle_crypt_func*) aes_encrypt;
      ctx->auth = (auth_func)gcm_aes_update;
      ctx->tag = (tag_func)gcm_aes_digest;
      ctx->ctx_ptr = &ctx->ctx.aes_gcm;
      ctx->block_size = AES_BLOCK_SIZE;
      break;
    case GNUTLS_CIPHER_CAMELLIA_128_CBC:
    case GNUTLS_CIPHER_CAMELLIA_192_CBC:
    case GNUTLS_CIPHER_CAMELLIA_256_CBC:
      ctx->encrypt = cbc_encrypt;
      ctx->decrypt = cbc_decrypt;
      ctx->i_encrypt = (nettle_crypt_func*)camellia_crypt;
      ctx->i_decrypt = (nettle_crypt_func*)camellia_crypt;
      ctx->ctx_ptr = &ctx->ctx.camellia;
      ctx->block_size = CAMELLIA_BLOCK_SIZE;
      break;
    case GNUTLS_CIPHER_AES_128_CBC:
    case GNUTLS_CIPHER_AES_192_CBC:
    case GNUTLS_CIPHER_AES_256_CBC:
      ctx->encrypt = cbc_encrypt;
      ctx->decrypt = cbc_decrypt;
      ctx->i_encrypt = (nettle_crypt_func*)aes_encrypt;
      ctx->i_decrypt = (nettle_crypt_func*)aes_decrypt;
      ctx->ctx_ptr = &ctx->ctx.aes;
      ctx->block_size = AES_BLOCK_SIZE;
      break;
    case GNUTLS_CIPHER_3DES_CBC:
      ctx->encrypt = cbc_encrypt;
      ctx->decrypt = cbc_decrypt;
      ctx->i_encrypt = (nettle_crypt_func *) des3_encrypt;
      ctx->i_decrypt = (nettle_crypt_func *) des3_decrypt;
      ctx->ctx_ptr = &ctx->ctx.des3;
      ctx->block_size = DES3_BLOCK_SIZE;
      break;
    case GNUTLS_CIPHER_DES_CBC:
      ctx->encrypt = cbc_encrypt;
      ctx->decrypt = cbc_decrypt;
      ctx->i_encrypt = (nettle_crypt_func *) des_encrypt;
      ctx->i_decrypt = (nettle_crypt_func *) des_decrypt;
      ctx->ctx_ptr = &ctx->ctx.des;
      ctx->block_size = DES_BLOCK_SIZE;
      break;
    case GNUTLS_CIPHER_ARCFOUR_128:
    case GNUTLS_CIPHER_ARCFOUR_40:
      ctx->encrypt = stream_encrypt;
      ctx->decrypt = stream_encrypt;
      ctx->i_encrypt = (nettle_crypt_func *) arcfour_crypt;
      ctx->i_decrypt = (nettle_crypt_func *) arcfour_crypt;
      ctx->ctx_ptr = &ctx->ctx.arcfour;
      ctx->block_size = 1;
      break;
    case GNUTLS_CIPHER_SALSA20_256:
      ctx->encrypt = stream_encrypt;
      ctx->decrypt = stream_encrypt;
      ctx->i_encrypt = (nettle_crypt_func *) salsa20_crypt;
      ctx->i_decrypt = (nettle_crypt_func *) salsa20_crypt;
      ctx->ctx_ptr = &ctx->ctx.salsa20;
      ctx->block_size = 1;
      break;
    case GNUTLS_CIPHER_ESTREAM_SALSA20_256:
      ctx->encrypt = stream_encrypt;
      ctx->decrypt = stream_encrypt;
      ctx->i_encrypt = (nettle_crypt_func *) salsa20r12_crypt;
      ctx->i_decrypt = (nettle_crypt_func *) salsa20r12_crypt;
      ctx->ctx_ptr = &ctx->ctx.salsa20;
      ctx->block_size = 1;
      break;
    case GNUTLS_CIPHER_RC2_40_CBC:
      ctx->encrypt = cbc_encrypt;
      ctx->decrypt = cbc_decrypt;
      ctx->i_encrypt = (nettle_crypt_func *) arctwo_encrypt;
      ctx->i_decrypt = (nettle_crypt_func *) arctwo_decrypt;
      ctx->ctx_ptr = &ctx->ctx.arctwo;
      ctx->block_size = ARCTWO_BLOCK_SIZE;
      break;
    default:
      gnutls_assert ();
      gnutls_free(ctx);
      return GNUTLS_E_INVALID_REQUEST;
    }

  *_ctx = ctx;

  return 0;
}
示例#28
0
/*-
 * _gnutls_privkey_import_system:
 * @pkey: The private key
 * @url: The URL of the key
 *
 * This function will import the given private key to the abstract
 * #gnutls_privkey_t type. 
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.4.0
 *
 -*/
int
_gnutls_privkey_import_system_url(gnutls_privkey_t pkey,
			          const char *url)
{
	uint8_t id[MAX_WID_SIZE];
	HCERTSTORE store = NULL;
	size_t id_size;
	const CERT_CONTEXT *cert = NULL;
	CRYPT_HASH_BLOB blob;
	CRYPT_KEY_PROV_INFO *kpi = NULL;
	NCRYPT_KEY_HANDLE nc = NULL;
	NCRYPT_PROV_HANDLE sctx = NULL;
	DWORD kpi_size;
	SECURITY_STATUS r;
	int ret, enc_too = 0;
	WCHAR algo_str[64];
	DWORD algo_str_size = 0;
	priv_st *priv;

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

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

	priv = gnutls_calloc(1, sizeof(*priv));
	if (priv == NULL)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	id_size = sizeof(id);
	ret = get_id(url, id, &id_size, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);

	blob.cbData = id_size;
	blob.pbData = id;

	store = CertOpenSystemStore(0, "MY");
	if (store == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_FILE_ERROR;
		goto cleanup;
	}

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

	if (cert == NULL) {
		char buf[64];
		_gnutls_debug_log("cannot find ID: %s from %s\n",
			      _gnutls_bin2hex(id, id_size,
					      buf, sizeof(buf), NULL),
				url);
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	kpi_size = 0;
	r = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID,
					      NULL, &kpi_size);
	if (r == 0) {
		_gnutls_debug_log("error in getting context: %d from %s\n",
			      	  (int)GetLastError(), url);
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	kpi = gnutls_malloc(kpi_size);
	if (kpi == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}

	r = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID,
					      kpi, &kpi_size);
	if (r == 0) {
		_gnutls_debug_log("error in getting context: %d from %s\n",
			      	  (int)GetLastError(), url);
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	r = pNCryptOpenStorageProvider(&sctx, kpi->pwszProvName, 0);
	if (FAILED(r)) {
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	r = pNCryptOpenKey(sctx, &nc, kpi->pwszContainerName, 0, 0);
	if (FAILED(r)) {
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	r = pNCryptGetProperty(nc, NCRYPT_ALGORITHM_PROPERTY,
				(BYTE*)algo_str, sizeof(algo_str),
				&algo_str_size, 0);
	if (FAILED(r)) {
		ret = gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
		goto cleanup;
	}

	if (StrCmpW(algo_str, BCRYPT_RSA_ALGORITHM) == 0) {
		priv->pk = GNUTLS_PK_RSA;
		priv->sign_algo = GNUTLS_SIGN_RSA_SHA256;
		enc_too = 1;
	} else if (StrCmpW(algo_str, BCRYPT_DSA_ALGORITHM) == 0) {
		priv->pk = GNUTLS_PK_DSA;
		priv->sign_algo = GNUTLS_SIGN_DSA_SHA1;
	} else if (StrCmpW(algo_str, BCRYPT_ECDSA_P256_ALGORITHM) == 0) {
		priv->pk = GNUTLS_PK_EC;
		priv->sign_algo = GNUTLS_SIGN_ECDSA_SHA256;
	} else if (StrCmpW(algo_str, BCRYPT_ECDSA_P384_ALGORITHM) == 0) {
		priv->pk = GNUTLS_PK_EC;
		priv->sign_algo = GNUTLS_SIGN_ECDSA_SHA384;
	} else if (StrCmpW(algo_str, BCRYPT_ECDSA_P521_ALGORITHM) == 0) {
		priv->pk = GNUTLS_PK_EC;
		priv->sign_algo = GNUTLS_SIGN_ECDSA_SHA512;
	} else {
		_gnutls_debug_log("unknown key algorithm: %ls\n", algo_str);
		ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
		goto cleanup;
	}
	priv->nc = nc;

	ret = gnutls_privkey_import_ext3(pkey, priv, cng_sign,
					 (enc_too!=0)?cng_decrypt:NULL,
					 cng_deinit,
					 cng_info, 0);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = 0;
 cleanup:
	if (ret < 0) {
		if (nc != 0)
			pNCryptFreeObject(nc);
		gnutls_free(priv);
	}
	if (sctx != 0)
		pNCryptFreeObject(sctx);

	gnutls_free(kpi);
	CertCloseStore(store, 0);
	return ret;
}
示例#29
0
static void
server (struct params_res *params)
{
  size_t t;

  /* this must be called once in the program, it is mostly for the server.
   */
  if (debug)
    {
      gnutls_global_set_log_function (tls_log_func);
      gnutls_global_set_log_level (2);
    }

  gnutls_global_init ();
  gnutls_anon_allocate_server_credentials (&anoncred);

  if (debug)
    success ("Launched, generating DH parameters...\n");

  generate_dh_params ();

  gnutls_anon_set_server_dh_params (anoncred, dh_params);

  if (params->enable_db)
    {
      wrap_db_init ();
    }
#ifdef ENABLE_SESSION_TICKET
  if (params->enable_session_ticket_server)
    gnutls_session_ticket_key_generate (&session_ticket_key);
#endif

  for (t = 0; t < 2; t++)
    {
      client_len = sizeof (sa_cli);

      session = initialize_tls_session (params);

      sd = accept (listen_sd, (SA *) & sa_cli, &client_len);

      if (debug)
	success ("server: connection from %s, port %d\n",
		 inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf,
			    sizeof (topbuf)), ntohs (sa_cli.sin_port));

      gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
      ret = gnutls_handshake (session);
      if (ret < 0)
	{
	  close (sd);
	  gnutls_deinit (session);
	  fail ("server: Handshake has failed (%s)\n\n",
		gnutls_strerror (ret));
	  return;
	}
      if (debug)
	success ("server: Handshake was completed\n");

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

      i = 0;
      for (;;)
	{
	  memset (buffer, 0, MAX_BUF + 1);
	  ret = gnutls_record_recv (session, buffer, MAX_BUF);

	  if (ret == 0)
	    {
	      if (debug)
		success ("server: Peer has closed the GnuTLS connection\n");
	      break;
	    }
	  else if (ret < 0)
	    {
	      fail ("server: Received corrupted data(%d). Closing...\n", ret);
	      break;
	    }
	  else if (ret > 0)
	    {
	      /* echo data back to the client
	       */
	      gnutls_record_send (session, buffer, strlen (buffer));
	    }
	}
      /* do not wait for the peer to close the connection.
       */
      gnutls_bye (session, GNUTLS_SHUT_WR);

      close (sd);

      gnutls_deinit (session);
    }

  close (listen_sd);

  if (params->enable_db)
    {
      wrap_db_deinit ();
    }

  gnutls_free (session_ticket_key.data);
  session_ticket_key.data = NULL;

  if (debug)
    success ("server: finished\n");
}
示例#30
0
/* Decodes the PKCS #7 signed data, and returns an ASN1_TYPE, 
 * which holds them. If raw is non null then the raw decoded
 * data are copied (they are locally allocated) there.
 */
static int
_decode_pkcs7_signed_data(ASN1_TYPE pkcs7, ASN1_TYPE * sdata,
			  gnutls_datum_t * raw)
{
	char oid[MAX_OID_SIZE];
	ASN1_TYPE c2;
	uint8_t *tmp = NULL;
	int tmp_size, len, result;

	len = sizeof(oid) - 1;
	result = asn1_read_value(pkcs7, "contentType", oid, &len);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		return _gnutls_asn2err(result);
	}

	if (strcmp(oid, SIGNED_DATA_OID) != 0) {
		gnutls_assert();
		_gnutls_debug_log("Unknown PKCS7 Content OID '%s'\n", oid);
		return GNUTLS_E_UNKNOWN_PKCS_CONTENT_TYPE;
	}

	if ((result = asn1_create_element
	     (_gnutls_get_pkix(), "PKIX1.pkcs-7-SignedData",
	      &c2)) != ASN1_SUCCESS) {
		gnutls_assert();
		return _gnutls_asn2err(result);
	}

	/* the Signed-data has been created, so
	 * decode them.
	 */
	tmp_size = 0;
	result = asn1_read_value(pkcs7, "content", NULL, &tmp_size);
	if (result != ASN1_MEM_ERROR) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	tmp = gnutls_malloc(tmp_size);
	if (tmp == NULL) {
		gnutls_assert();
		result = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}

	result = asn1_read_value(pkcs7, "content", tmp, &tmp_size);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	/* tmp, tmp_size hold the data and the size of the CertificateSet structure
	 * actually the ANY stuff.
	 */

	/* Step 1. In case of a signed structure extract certificate set.
	 */

	result = asn1_der_decoding(&c2, tmp, tmp_size, NULL);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	if (raw == NULL) {
		gnutls_free(tmp);
	} else {
		raw->data = tmp;
		raw->size = tmp_size;
	}

	*sdata = c2;

	return 0;

      cleanup:
	if (c2)
		asn1_delete_structure(&c2);
	gnutls_free(tmp);
	return result;
}