コード例 #1
0
ファイル: Plugin.cpp プロジェクト: nicolas-bertrand/lightbird
bool    Plugin::onLoad(LightBird::IApi *api)
{
    int         error;
    const char  *err_pos = NULL;

    this->api = api;
    try
    {
        ASSERT_INIT(gnutls_global_init(), "global");
        if (!gnutls_check_version(GNUTLS_CHECK_VERSION))
            throw Properties("error", "Bad GnuTLS version").add("version required", GNUTLS_CHECK_VERSION);
        gnutls_global_set_audit_log_function(Plugin::log);
        this->_loadConfiguration();
        this->_loadPrivateKey();
        this->_loadCertificate();
        this->_loadDHParams();
        ASSERT_INIT(gnutls_certificate_allocate_credentials(&this->x509_cred), "credentials");
        ASSERT(gnutls_certificate_set_x509_key(this->x509_cred, &this->crt, 1, this->key));
        ASSERT_INIT(gnutls_priority_init(&this->priority, this->priorityStrings.data(), &err_pos), "priority");
        gnutls_certificate_set_dh_params(this->x509_cred, this->dhParams);
    }
    catch (Properties p)
    {
        if (err_pos)
            p.add("error position", err_pos).add("priority string", this->priorityStrings);
        LOG_FATAL("Unable to initialize GnuTLS", p.toMap(), "Plugin", "onLoad");
        this->_deinit();
        return (false);
    }
    this->api->contexts().declareInstance("handshake", (this->handshake = new Handshake(this->api, this->handshakeTimeout)));
    this->api->contexts().declareInstance("record", (this->record = new Record(this->api)));
    return (true);
}
コード例 #2
0
int tls_certificates_load(gnutls_x509_privkey key, const char *certfname, gnutls_certificate_credentials cred)
{
    int ret;
    size_t size;
    gnutls_datum certfile;
    unsigned int cert_max, i;
    gnutls_x509_crt certs[1024];

    ret = _requiem_load_file(certfname, &certfile.data, &size);
    if ( ret < 0 )
        return ret;
    certfile.size = (unsigned int) size;

    cert_max = sizeof(certs) / sizeof(*certs);
    ret = _requiem_tls_crt_list_import(certs, &cert_max, &certfile, GNUTLS_X509_FMT_PEM);
    if ( ret < 0 ) {
        ret = requiem_error_verbose(REQUIEM_ERROR_PROFILE, "error importing certificate listing: %s", gnutls_strerror(ret));
        goto err;
    }

    for ( i = 0; i < cert_max; i++) {
        ret = gnutls_certificate_set_x509_key(cred, &certs[i], 1, key);
        gnutls_x509_crt_deinit(certs[i]);

        if ( ret < 0 ) {
            ret = requiem_error_verbose(REQUIEM_ERROR_PROFILE, "error importing certificate: %s", gnutls_strerror(ret));
            break;
        }
    }

err:
    _requiem_unload_file(certfile.data, certfile.size);

    return ret;
}
コード例 #3
0
void certificate_credentials::set_x509_key (gnutls_x509_crt_t * cert_list,
        int cert_list_size,
        gnutls_x509_privkey_t key)
{
    RETWRAP (gnutls_certificate_set_x509_key
             (cred, cert_list, cert_list_size, key));
}
コード例 #4
0
static gboolean
infinoted_startup_load_credentials(InfinotedStartup* startup,
                                   GError** error)
{
  gnutls_x509_crt_t* certs;
  guint n_certs;
  gnutls_certificate_credentials_t creds;
  int res;

  if(startup->options->security_policy !=
     INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED)
  {
    startup->private_key = infinoted_startup_load_key(
      startup->log,
      startup->options->create_key,
      startup->options->key_file,
      error
    );

    if(startup->private_key == NULL)
      return FALSE;

    certs = infinoted_startup_load_certificate(
      startup->log,
      startup->options->create_certificate,
      startup->private_key,
      startup->options->certificate_file,
      startup->options->certificate_chain_file,
      &n_certs,
      error
    );

    if(certs == NULL)
      return FALSE;

    /* Takes ownership of certificates: */
    startup->certificates = inf_certificate_chain_new(certs, n_certs);

    startup->credentials = inf_certificate_credentials_new();
    creds = inf_certificate_credentials_get(startup->credentials);

    res = gnutls_certificate_set_x509_key(
      creds,
      inf_certificate_chain_get_raw(startup->certificates),
      inf_certificate_chain_get_n_certificates(startup->certificates),
      startup->private_key
    );

    if(res != 0)
    {
      inf_gnutls_set_error(error, res);
      return FALSE;
    }
  }

  return TRUE;
}
コード例 #5
0
ファイル: ufwissl_gnutls_ctx.c プロジェクト: maximerobin/Ufwi
int ufwissl_ssl_context_keypair_from_data(ufwissl_ssl_context * ctx,
					ufwissl_ssl_client_cert * cert)
{
	int ret;
	ret = gnutls_certificate_set_x509_key(ctx->cred, &cert->cert.subject,
					    1, cert->pkey);
	if (ret != 0)
		return UFWISSL_ERROR;
	gnutls_certificate_set_dh_params(ctx->cred, ctx->dh);

	return (ret == 0) ? UFWISSL_OK : UFWISSL_ERROR;
}
コード例 #6
0
ファイル: set_x509_key_utf8.c プロジェクト: gnutls/gnutls
static int import_key(gnutls_certificate_credentials_t xcred, const gnutls_datum_t *skey, const gnutls_datum_t *cert)
{
	gnutls_x509_privkey_t key;
	gnutls_x509_crt_t *crt_list;
	unsigned crt_list_size, idx, i;
	gnutls_datum_t tcert;
	int ret;

	assert(gnutls_x509_privkey_init(&key)>=0);

	ret = gnutls_x509_crt_list_import2(&crt_list, &crt_list_size, cert, GNUTLS_X509_FMT_PEM, 0);
	if (ret < 0) {
		fail("error in gnutls_x509_crt_list_import2: %s\n", gnutls_strerror(ret));
	}

	ret = gnutls_x509_privkey_import(key, skey, GNUTLS_X509_FMT_PEM);
	if (ret < 0) {
		fail("error in key import: %s\n", gnutls_strerror(ret));
	}

	ret = gnutls_certificate_set_x509_key(xcred, crt_list,
				crt_list_size, key);
	if (ret < 0) {
		success("error in gnutls_certificate_set_x509_key: %s\n", gnutls_strerror(ret));
		idx = ret;
		goto cleanup;
	}

	/* return index */
	idx = ret;

	/* verify whether the stored certificate match the ones we have */
	for (i=0;i<MIN(2, crt_list_size);i++) {
		ret = gnutls_certificate_get_crt_raw(xcred, idx, i, &tcert);
		if (ret < 0) {
			fail("error in %d: cert: %d: %s\n", __LINE__, i, gnutls_strerror(ret));
			exit(1);
		}

		compare(&tcert, cert->data+i);
	}

 cleanup:
	gnutls_x509_privkey_deinit(key);
	for (i=0;i<crt_list_size;i++) {
		gnutls_x509_crt_deinit(crt_list[i]);
	}
	gnutls_free(crt_list);

	return idx;
}
コード例 #7
0
ファイル: certificatemanager.cpp プロジェクト: Kaligule/gobby
void Gobby::CertificateManager::make_credentials()
{
	InfCertificateCredentials* creds = inf_certificate_credentials_new();
	gnutls_certificate_credentials_t gnutls_creds =
		inf_certificate_credentials_get(creds);

	if(m_preferences.security.authentication_enabled &&
	   m_key != NULL && m_certificates != NULL)
	{
		gnutls_certificate_set_x509_key(
			gnutls_creds,
			inf_certificate_chain_get_raw(m_certificates),
			inf_certificate_chain_get_n_certificates(m_certificates),
			m_key
		);
	}

	if(m_preferences.security.use_system_trust)
	{
		const int n_cas = gnutls_certificate_set_x509_system_trust(
			gnutls_creds);
		if(n_cas < 0)
		{
			g_warning("Failed to add system CAs: %s\n",
				gnutls_strerror(n_cas));
		}
	}

	if(!m_trust.empty())
	{
		gnutls_certificate_set_x509_trust(
			gnutls_creds,
			&m_trust[0],
			m_trust.size()
		);
	}

	if(m_dh_params != NULL)
		gnutls_certificate_set_dh_params(gnutls_creds, m_dh_params);

	gnutls_certificate_set_verify_flags(
		gnutls_creds, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);

	InfCertificateCredentials* old_creds = m_credentials;
	m_credentials = creds;

	m_signal_credentials_changed.emit();

	if(old_creds != NULL)
		inf_certificate_credentials_unref(old_creds);
}
コード例 #8
0
		X509Credentials(const std::string& certstr, const std::string& keystr)
			: key(keystr)
			, certs(certstr)
		{
			// Throwing is ok here, the destructor of Credentials is called in that case
			int ret = gnutls_certificate_set_x509_key(cred, certs.raw(), certs.size(), key.get());
			ThrowOnError(ret, "Unable to set cert/key pair");

#ifdef GNUTLS_NEW_CERT_CALLBACK_API
			gnutls_certificate_set_retrieve_function(cred, cert_callback);
#else
			gnutls_certificate_client_set_retrieve_function(cred, cert_callback);
#endif
		}
コード例 #9
0
ファイル: auto-verify.c プロジェクト: gnutls/gnutls
static
void test_success2(const char *name, const char *prio)
{
	int ret;
	/* Server stuff. */
	gnutls_certificate_credentials_t serverx509cred;
	gnutls_session_t server;
	int sret = GNUTLS_E_AGAIN;
	/* Client stuff. */
	gnutls_certificate_credentials_t clientx509cred;
	gnutls_session_t client;
	int cret = GNUTLS_E_AGAIN;
	gnutls_x509_crt_t *crts;
	unsigned int crts_size;
	unsigned i;
	gnutls_x509_privkey_t pkey;
	unsigned status;

	success("testing cert verification success2 for %s\n", name);

	to_server_len = 0;
	to_client_len = 0;

	ret = gnutls_x509_crt_list_import2(&crts, &crts_size, &server_cert, GNUTLS_X509_FMT_PEM,
			GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED);
	if (ret < 0) {
		fprintf(stderr, "error: %s\n", gnutls_strerror(ret));
		exit(1);
	}

	ret = gnutls_x509_privkey_init(&pkey);
	if (ret < 0) {
		fprintf(stderr, "error: %s\n", gnutls_strerror(ret));
		exit(1);
	}

	ret =
	    gnutls_x509_privkey_import(pkey, &server_key,
					GNUTLS_X509_FMT_PEM);
	if (ret < 0) {
		fprintf(stderr, "error: %s\n", gnutls_strerror(ret));
		exit(1);
	}

	/* Init server */
	gnutls_certificate_allocate_credentials(&serverx509cred);
	gnutls_certificate_set_x509_key(serverx509cred, crts, crts_size, pkey);
	gnutls_x509_privkey_deinit(pkey);
	for (i=0;i<crts_size;i++)
		gnutls_x509_crt_deinit(crts[i]);
	gnutls_free(crts);

	gnutls_init(&server, GNUTLS_SERVER);
	gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
				serverx509cred);
	assert(gnutls_priority_set_direct(server,
				   prio,
				   NULL)>=0);
	gnutls_transport_set_push_function(server, server_push);
	gnutls_transport_set_pull_function(server, server_pull);
	gnutls_transport_set_ptr(server, server);
	gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUEST);

	/* Init client */
	/* Init client */
	ret = gnutls_certificate_allocate_credentials(&clientx509cred);
	if (ret < 0)
		exit(1);

	ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM);
	if (ret < 0)
		exit(1);

	ret = gnutls_certificate_set_x509_key_mem(clientx509cred,
						  &cli_cert, &cli_key,
						  GNUTLS_X509_FMT_PEM);

	ret = gnutls_init(&client, GNUTLS_CLIENT);
	if (ret < 0)
		exit(1);

	ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
				clientx509cred);
	if (ret < 0)
		exit(1);

	assert(gnutls_priority_set_direct(client, prio, NULL)>=0);
	gnutls_transport_set_push_function(client, client_push);
	gnutls_transport_set_pull_function(client, client_pull);
	gnutls_transport_set_ptr(client, client);

	gnutls_session_set_verify_cert(client, "localhost", 0);

	HANDSHAKE(client, server);

	status = gnutls_session_get_verify_cert_status(client);

	if (status != 0) {
		fail("%s: should have accepted: %u!\n", __func__, status);
		exit(1);
	}

	gnutls_deinit(client);
	gnutls_deinit(server);

	gnutls_certificate_free_credentials(serverx509cred);
	gnutls_certificate_free_credentials(clientx509cred);
}
コード例 #10
0
ファイル: auto-verify.c プロジェクト: gnutls/gnutls
static
void test_failure(const char *name, const char *prio)
{
	int ret;
	/* Server stuff. */
	gnutls_certificate_credentials_t serverx509cred;
	gnutls_session_t server;
	int sret = GNUTLS_E_AGAIN;
	/* Client stuff. */
	gnutls_certificate_credentials_t clientx509cred;
	gnutls_session_t client;
	int cret = GNUTLS_E_AGAIN;
	gnutls_x509_crt_t *crts;
	unsigned int crts_size;
	unsigned i;
	gnutls_typed_vdata_st vdata[2];
	gnutls_x509_privkey_t pkey;
	unsigned status;

	success("testing cert verification failure for %s\n", name);

	to_server_len = 0;
	to_client_len = 0;

	ret = gnutls_x509_crt_list_import2(&crts, &crts_size, &server_cert, GNUTLS_X509_FMT_PEM,
			GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED);
	if (ret < 0) {
		fprintf(stderr, "error: %s\n", gnutls_strerror(ret));
		exit(1);
	}

	ret = gnutls_x509_privkey_init(&pkey);
	if (ret < 0) {
		fprintf(stderr, "error: %s\n", gnutls_strerror(ret));
		exit(1);
	}

	ret =
	    gnutls_x509_privkey_import(pkey, &server_key,
					GNUTLS_X509_FMT_PEM);
	if (ret < 0) {
		fprintf(stderr, "error: %s\n", gnutls_strerror(ret));
		exit(1);
	}

	/* Init server */
	gnutls_certificate_allocate_credentials(&serverx509cred);
	gnutls_certificate_set_x509_key(serverx509cred, crts, crts_size, pkey);
	gnutls_x509_privkey_deinit(pkey);
	for (i=0;i<crts_size;i++)
		gnutls_x509_crt_deinit(crts[i]);
	gnutls_free(crts);

	gnutls_init(&server, GNUTLS_SERVER);
	gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
				serverx509cred);
	assert(gnutls_priority_set_direct(server,
				   prio,
				   NULL) >= 0);
	gnutls_transport_set_push_function(server, server_push);
	gnutls_transport_set_pull_function(server, server_pull);
	gnutls_transport_set_ptr(server, server);
	gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUEST);

	/* Init client */
	/* Init client */
	ret = gnutls_certificate_allocate_credentials(&clientx509cred);
	if (ret < 0)
		exit(1);

	ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM);
	if (ret < 0)
		exit(1);

	ret = gnutls_certificate_set_x509_key_mem(clientx509cred,
						  &cli_cert, &cli_key,
						  GNUTLS_X509_FMT_PEM);

	ret = gnutls_init(&client, GNUTLS_CLIENT);
	if (ret < 0)
		exit(1);

	ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
				clientx509cred);
	if (ret < 0)
		exit(1);

	assert(gnutls_priority_set_direct(client, prio, NULL) >= 0);
	gnutls_transport_set_push_function(client, client_push);
	gnutls_transport_set_pull_function(client, client_pull);
	gnutls_transport_set_ptr(client, client);

	memset(vdata, 0, sizeof(vdata));

	/* check with wrong hostname */
	vdata[0].type = GNUTLS_DT_DNS_HOSTNAME;
	vdata[0].data = (void*)"localhost1";

	vdata[1].type = GNUTLS_DT_KEY_PURPOSE_OID;
	vdata[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER;

	gnutls_session_set_verify_cert2(client, vdata, 2, 0);

	HANDSHAKE_EXPECT(client, server, GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR, GNUTLS_E_AGAIN);

	status = gnutls_session_get_verify_cert_status(client);

	if (status == 0) {
		fail("should not have accepted!\n");
		exit(1);
	}

	gnutls_deinit(client);
	gnutls_deinit(server);

	gnutls_certificate_free_credentials(serverx509cred);
	gnutls_certificate_free_credentials(clientx509cred);
}
コード例 #11
0
static InfdXmppServer*
inf_test_certificate_setup_server(InfIo* io,
                                  const char* key_file,
                                  const char* cert_file,
                                  GError** error)
{
  InfdTcpServer* tcp;
  InfdXmppServer* xmpp;

  gnutls_x509_privkey_t key;
  GPtrArray* certs;
  InfCertificateCredentials* creds;
  guint i;
  int res;

  key = inf_cert_util_read_private_key(key_file, error);
  if(!key) return NULL;

  certs = inf_cert_util_read_certificate(cert_file, NULL, error);
  if(!certs)
  {
    gnutls_x509_privkey_deinit(key);
    return NULL;
  }

  creds = inf_certificate_credentials_new();
  res = gnutls_certificate_set_x509_key(
    inf_certificate_credentials_get(creds),
    (gnutls_x509_crt_t*)certs->pdata,
    certs->len,
    key
  );

  gnutls_x509_privkey_deinit(key);
  for(i = 0; i < certs->len; ++i)
    gnutls_x509_crt_deinit(certs->pdata[i]);
  g_ptr_array_free(certs, TRUE);

  if(res != 0)
  {
    inf_certificate_credentials_unref(creds);
    inf_gnutls_set_error(error, res);
    return NULL;
  }

  tcp = g_object_new(
    INFD_TYPE_TCP_SERVER,
    "io", io,
    "local-port", 6524,
    NULL
  );

  if(infd_tcp_server_open(tcp, error) == FALSE)
  {
    inf_certificate_credentials_unref(creds);
    return NULL;
  }

  xmpp = infd_xmpp_server_new(
    tcp,
    INF_XMPP_CONNECTION_SECURITY_ONLY_TLS,
    creds,
    NULL,
    NULL
  );

  /* Keep client connections alive */
  g_signal_connect(
    G_OBJECT(xmpp),
    "new-connection",
    G_CALLBACK(inf_test_certificate_validate_new_connection_cb),
    NULL
  );

  inf_certificate_credentials_unref(creds);
  return xmpp;
}
コード例 #12
0
ファイル: tls_g.c プロジェクト: 1ack/Impala
/*
 * initialize a new TLS context
 */
static int
tlsg_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
{
	tlsg_ctx *ctx = lo->ldo_tls_ctx;
	int rc;

 	if ( lo->ldo_tls_ciphersuite &&
		tlsg_parse_ciphers( ctx, lt->lt_ciphersuite )) {
 		Debug( LDAP_DEBUG_ANY,
 			   "TLS: could not set cipher list %s.\n",
 			   lo->ldo_tls_ciphersuite, 0, 0 );
		return -1;
 	}

	if (lo->ldo_tls_cacertdir != NULL) {
		Debug( LDAP_DEBUG_ANY, 
		       "TLS: warning: cacertdir not implemented for gnutls\n",
		       NULL, NULL, NULL );
	}

	if (lo->ldo_tls_cacertfile != NULL) {
		rc = gnutls_certificate_set_x509_trust_file( 
			ctx->cred,
			lt->lt_cacertfile,
			GNUTLS_X509_FMT_PEM );
		if ( rc < 0 ) return -1;
	}

	if ( lo->ldo_tls_certfile && lo->ldo_tls_keyfile ) {
		gnutls_x509_privkey_t key;
		gnutls_datum_t buf;
		gnutls_x509_crt_t certs[VERIFY_DEPTH];
		unsigned int max = VERIFY_DEPTH;

		rc = gnutls_x509_privkey_init( &key );
		if ( rc ) return -1;

		/* OpenSSL builds the cert chain for us, but GnuTLS
		 * expects it to be present in the certfile. If it's
		 * not, we have to build it ourselves. So we have to
		 * do some special checks here...
		 */
		rc = tlsg_getfile( lt->lt_keyfile, &buf );
		if ( rc ) return -1;
		rc = gnutls_x509_privkey_import( key, &buf,
			GNUTLS_X509_FMT_PEM );
		LDAP_FREE( buf.data );
		if ( rc < 0 ) return rc;

		rc = tlsg_getfile( lt->lt_certfile, &buf );
		if ( rc ) return -1;
		rc = gnutls_x509_crt_list_import( certs, &max, &buf,
			GNUTLS_X509_FMT_PEM, 0 );
		LDAP_FREE( buf.data );
		if ( rc < 0 ) return rc;

		/* If there's only one cert and it's not self-signed,
		 * then we have to build the cert chain.
		 */
		if ( max == 1 && !gnutls_x509_crt_check_issuer( certs[0], certs[0] )) {
			gnutls_x509_crt_t *cas;
			unsigned int i, j, ncas;

			gnutls_certificate_get_x509_cas( ctx->cred, &cas, &ncas );
			for ( i = 1; i<VERIFY_DEPTH; i++ ) {
				for ( j = 0; j<ncas; j++ ) {
					if ( gnutls_x509_crt_check_issuer( certs[i-1], cas[j] )) {
						certs[i] = cas[j];
						max++;
						/* If this CA is self-signed, we're done */
						if ( gnutls_x509_crt_check_issuer( cas[j], cas[j] ))
							j = ncas;
						break;
					}
				}
				/* only continue if we found a CA and it was not self-signed */
				if ( j == ncas )
					break;
			}
		}
		rc = gnutls_certificate_set_x509_key( ctx->cred, certs, max, key );
		if ( rc ) return -1;
	} else if ( lo->ldo_tls_certfile || lo->ldo_tls_keyfile ) {
		Debug( LDAP_DEBUG_ANY, 
		       "TLS: only one of certfile and keyfile specified\n",
		       NULL, NULL, NULL );
		return -1;
	}

	if ( lo->ldo_tls_dhfile ) {
		Debug( LDAP_DEBUG_ANY, 
		       "TLS: warning: ignoring dhfile\n", 
		       NULL, NULL, NULL );
	}

	if ( lo->ldo_tls_crlfile ) {
		rc = gnutls_certificate_set_x509_crl_file( 
			ctx->cred,
			lt->lt_crlfile,
			GNUTLS_X509_FMT_PEM );
		if ( rc < 0 ) return -1;
		rc = 0;
	}

	/* FIXME: ITS#5992 - this should go be configurable,
	 * and V1 CA certs should be phased out ASAP.
	 */
	gnutls_certificate_set_verify_flags( ctx->cred,
		GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT );

	if ( is_server ) {
		gnutls_dh_params_init(&ctx->dh_params);
		gnutls_dh_params_generate2(ctx->dh_params, DH_BITS);
	}
	return 0;
}
コード例 #13
0
void doit(void)
{
	int exit_code = EXIT_SUCCESS;
	int ret;
	/* Server stuff. */
	gnutls_certificate_credentials_t serverx509cred;
	gnutls_session_t server;
	int sret = GNUTLS_E_AGAIN;
	/* Client stuff. */
	gnutls_certificate_credentials_t clientx509cred;
	gnutls_session_t client;
	int cret = GNUTLS_E_AGAIN;
	gnutls_x509_crt_t *crts;
	unsigned int crts_size;
	unsigned i;
	gnutls_x509_privkey_t pkey;

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

	ret = gnutls_x509_crt_list_import2(&crts, &crts_size, &server_cert, GNUTLS_X509_FMT_PEM,
			GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED);
	if (ret < 0) {
		fprintf(stderr, "error: %s\n", gnutls_strerror(ret));
		exit(1);
	}

	ret = gnutls_x509_privkey_init(&pkey);
	if (ret < 0) {
		fprintf(stderr, "error: %s\n", gnutls_strerror(ret));
		exit(1);
	}

	ret =
	    gnutls_x509_privkey_import(pkey, &server_key,
				       GNUTLS_X509_FMT_PEM);
	if (ret < 0) {
		fprintf(stderr, "error: %s\n", gnutls_strerror(ret));
		exit(1);
	}

	/* Init server */
	gnutls_certificate_allocate_credentials(&serverx509cred);
	gnutls_certificate_set_x509_key(serverx509cred, crts, crts_size, pkey);
	gnutls_x509_privkey_deinit(pkey);
	for (i=0;i<crts_size;i++)
		gnutls_x509_crt_deinit(crts[i]);
	gnutls_free(crts);

	gnutls_init(&server, GNUTLS_SERVER);
	gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
			       serverx509cred);
	gnutls_priority_set_direct(server,
				   "NORMAL:-CIPHER-ALL:+AES-128-GCM",
				   NULL);
	gnutls_transport_set_push_function(server, server_push);
	gnutls_transport_set_pull_function(server, server_pull);
	gnutls_transport_set_ptr(server, server);
	gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUEST);

	/* Init client */
	/* Init client */
	ret = gnutls_certificate_allocate_credentials(&clientx509cred);
	if (ret < 0)
		exit(1);

	ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM);
	if (ret < 0)
		exit(1);

	gnutls_certificate_set_retrieve_function2(clientx509cred, cert_callback);

	ret = gnutls_init(&client, GNUTLS_CLIENT);
	if (ret < 0)
		exit(1);

	ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
			       clientx509cred);
	if (ret < 0)
		exit(1);

	gnutls_priority_set_direct(client, "NORMAL", NULL);
	gnutls_transport_set_push_function(client, client_push);
	gnutls_transport_set_pull_function(client, client_pull);
	gnutls_transport_set_ptr(client, client);

	HANDSHAKE(client, server);

	if (gnutls_certificate_get_ours(client) == NULL) {
		fail("client certificate was not sent!\n");
		exit(1);
	}

	/* check gnutls_certificate_get_ours() - server side */
	{
		const gnutls_datum_t *mcert;
		gnutls_datum_t scert;
		gnutls_x509_crt_t crt;

		mcert = gnutls_certificate_get_ours(server);
		if (mcert == NULL) {
			fail("gnutls_certificate_get_ours(): failed\n");
			exit(1);
		}

		gnutls_x509_crt_init(&crt);
		ret = gnutls_x509_crt_import(crt, &server_cert, GNUTLS_X509_FMT_PEM);
		if (ret < 0) {
			fail("gnutls_x509_crt_import: %s\n", gnutls_strerror(ret));
			exit(1);
		}

		ret = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &scert);
		if (ret < 0) {
			fail("gnutls_x509_crt_export2: %s\n", gnutls_strerror(ret));
			exit(1);
		}
		gnutls_x509_crt_deinit(crt);

		if (scert.size != mcert->size || memcmp(scert.data, mcert->data, mcert->size) != 0) {
			fail("gnutls_certificate_get_ours output doesn't match cert\n");
			exit(1);
		}
		gnutls_free(scert.data);
	}

	/* check gnutls_certificate_get_ours() - client side */
	{
		const gnutls_datum_t *mcert;
		gnutls_datum_t ccert;
		gnutls_x509_crt_t crt;

		mcert = gnutls_certificate_get_ours(client);
		if (mcert == NULL) {
			fail("gnutls_certificate_get_ours(): failed\n");
			exit(1);
		}

		gnutls_x509_crt_init(&crt);
		ret = gnutls_x509_crt_import(crt, &cli_cert, GNUTLS_X509_FMT_PEM);
		if (ret < 0) {
			fail("gnutls_x509_crt_import: %s\n", gnutls_strerror(ret));
			exit(1);
		}

		ret = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &ccert);
		if (ret < 0) {
			fail("gnutls_x509_crt_export2: %s\n", gnutls_strerror(ret));
			exit(1);
		}
		gnutls_x509_crt_deinit(crt);

		if (ccert.size != mcert->size || memcmp(ccert.data, mcert->data, mcert->size) != 0) {
			fail("gnutls_certificate_get_ours output doesn't match cert\n");
			exit(1);
		}
		gnutls_free(ccert.data);
	}

	/* check the number of certificates received */
	{
		unsigned cert_list_size = 0;
		gnutls_typed_vdata_st data[2];
		unsigned status;

		memset(data, 0, sizeof(data));

		/* check with wrong hostname */
		data[0].type = GNUTLS_DT_DNS_HOSTNAME;
		data[0].data = (void*)"localhost1";

		data[1].type = GNUTLS_DT_KEY_PURPOSE_OID;
		data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER;

		gnutls_certificate_get_peers(client, &cert_list_size);
		if (cert_list_size < 2) {
			fprintf(stderr, "received a certificate list of %d!\n", cert_list_size);
			exit(1);
		}

		ret = gnutls_certificate_verify_peers(client, data, 2, &status);
		if (ret < 0) {
			fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret));
			exit(1);
		}

		if (status == 0) {
			fprintf(stderr, "should not have accepted!\n");
			exit(1);
		}

		/* check with wrong purpose */
		data[0].type = GNUTLS_DT_DNS_HOSTNAME;
		data[0].data = (void*)"localhost";

		data[1].type = GNUTLS_DT_KEY_PURPOSE_OID;
		data[1].data = (void*)GNUTLS_KP_TLS_WWW_CLIENT;

		gnutls_certificate_get_peers(client, &cert_list_size);
		if (cert_list_size < 2) {
			fprintf(stderr, "received a certificate list of %d!\n", cert_list_size);
			exit(1);
		}

		ret = gnutls_certificate_verify_peers(client, data, 2, &status);
		if (ret < 0) {
			fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret));
			exit(1);
		}

		if (status == 0) {
			fprintf(stderr, "should not have accepted!\n");
			exit(1);
		}

		/* check with correct purpose */
		data[0].type = GNUTLS_DT_DNS_HOSTNAME;
		data[0].data = (void*)"localhost";

		data[1].type = GNUTLS_DT_KEY_PURPOSE_OID;
		data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER;

		ret = gnutls_certificate_verify_peers(client, data, 2, &status);
		if (ret < 0) {
			fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret));
			exit(1);
		}

		if (status != 0) {
			fprintf(stderr, "could not verify certificate: %.4x\n", status);
			exit(1);
		}
	}

	if (gnutls_certificate_client_get_request_status(client) == 0) {
		fail("gnutls_certificate_client_get_request_status - 2 failed\n");
		exit(1);
	}

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

	gnutls_deinit(client);
	gnutls_deinit(server);

	gnutls_certificate_free_credentials(serverx509cred);
	gnutls_certificate_free_credentials(clientx509cred);

	gnutls_global_deinit();

	if (debug > 0) {
		if (exit_code == 0)
			puts("Self-test successful");
		else
			puts("Self-test failed");
	}
}
コード例 #14
0
ファイル: tls.c プロジェクト: gvsurenderreddy/iprohc
bool load_p12(gnutls_certificate_credentials_t xcred,
				  const char *const p12_file,
				  const char *const password)
{
	FILE*p12file;
	gnutls_datum_t p12blob;
	gnutls_pkcs12_t p12 = NULL;

	gnutls_x509_privkey_t key = NULL;
	gnutls_x509_crt_t certs[MAX_CERTS];
	int certs_nr;
	int id_cert;

	uint8_t key_id[20];
	size_t key_id_size;

	bool is_success = false;
	int ret;
	int i;

	assert(p12_file != NULL);

	/* Read file */
	p12file = fopen(p12_file, "rb");
	if(p12file == NULL)
	{
		trace(LOG_ERR, "failed to open PKCS#12 file '%s': %s (%d)", p12_file,
				strerror(errno), errno);
		ret = GNUTLS_E_FILE_ERROR;
		goto error;
	}
	p12blob.data = malloc(32768 * sizeof(char));
	p12blob.size = fread((void*) p12blob.data, sizeof(char), 32768, p12file);
	fclose(p12file);

	/* Init structure and import P12 */
	ret = gnutls_pkcs12_init(&p12);
	if(ret < 0)
	{
		trace(LOG_ERR, "failed to init PKCS#12 object (%d)", ret);
		goto free_blob;
	}

	ret = gnutls_pkcs12_import(p12, &p12blob, GNUTLS_X509_FMT_DER, 0);
	if(ret < 0)
	{
		trace(LOG_ERR, "failed to import PKCS#12 data (%d)", ret);
		goto deinit_pkcs12;
	}

	if(password)
	{
		ret = gnutls_pkcs12_verify_mac(p12, password);
		if(ret < 0)
		{
			trace(LOG_ERR, "failed to verify PKCS#12 MAC (%d)", ret);
			goto deinit_pkcs12;
		}
	}

	/* extract the private key and the certificates from PKCS#12 */
	if(!tls_parse_pkcs12(&p12, password, &key, certs, &certs_nr))
	{
		trace(LOG_ERR, "failed to parse PKCS#12 file '%s'", p12_file);
		goto deinit_pkcs12;
	}
	if(certs_nr < 2)
	{
		trace(LOG_ERR, "too few certificates in PKCS#12 file '%s'", p12_file);
		goto free_certs_key;
	}
	
	/* get the ID of private key */
	key_id_size = sizeof(key_id);
	ret = gnutls_x509_privkey_get_key_id(key, 0, key_id, &key_id_size);
	if(ret < 0)
	{
		trace(LOG_ERR, "failed to get key ID");
		goto free_certs_key;
	}

	id_cert = -1;
	for(i = 0; i < certs_nr; i++)
	{
		uint8_t cert_id[20];
		size_t cert_id_size;

		cert_id_size = sizeof(cert_id);
		ret = gnutls_x509_crt_get_key_id(certs[i], 0, cert_id, &cert_id_size);
		if(ret < 0)
		{
			trace(LOG_ERR, "failed to get key ID for certificate #%d (%d)", i, ret);
			goto free_certs_key;
		}

		if(key_id_size == cert_id_size &&
			memcmp(cert_id, key_id, cert_id_size) == 0)
		{
			/* it's the key certificate ! */
			if(id_cert != -1)
			{
				ret = GNUTLS_E_INTERRUPTED;
				trace(LOG_ERR, "Duplicate key certificate !\n");
				goto free_certs_key;
			}
			id_cert = i;
		}
	}

	if(id_cert == -1)
	{
		ret = GNUTLS_E_INTERRUPTED;
		trace(LOG_ERR, "Unable to find key certificate !\n");
		goto free_certs_key;
	}

	/* Now have fun with the key and certs ! */
	ret = gnutls_certificate_set_x509_key(xcred, &certs[id_cert], 1, key);
	if(ret < 0)
	{
		trace(LOG_ERR, "failed to set key for main certificate");
		goto free_certs_key;
	}

	for(i = 0; i < certs_nr; i++)
	{
		if(i != id_cert)
		{
			ret = gnutls_certificate_set_x509_trust(xcred, &certs[i], 1);
			if(ret < 0)
			{
				trace(LOG_ERR, "failed to trust certificate #%d", i + 1);
				goto free_certs_key;
			}
		}
	}

	is_success = true;

free_certs_key:
	gnutls_x509_privkey_deinit(key);
	for(i = 0; i < certs_nr; i++)
	{
		gnutls_x509_crt_deinit(certs[i]);
	}
deinit_pkcs12:
	gnutls_pkcs12_deinit(p12);
free_blob:
	free(p12blob.data);
error:
	return is_success;
}
コード例 #15
0
ファイル: cert-cred-x509.c プロジェクト: gnutls/gnutls
/**
 * gnutls_certificate_set_x509_simple_pkcs12_mem:
 * @res: is a #gnutls_certificate_credentials_t type.
 * @p12blob: the PKCS#12 blob.
 * @type: is PEM or DER of the @pkcs12file.
 * @password: optional password used to decrypt PKCS#12 file, bags and keys.
 *
 * This function sets a certificate/private key pair and/or a CRL in
 * the gnutls_certificate_credentials_t type.  This function may
 * be called more than once (in case multiple keys/certificates exist
 * for the server).
 *
 * Encrypted PKCS#12 bags and PKCS#8 private keys are supported.  However,
 * only password based security, and the same password for all
 * operations, are supported.
 *
 * PKCS#12 file may contain many keys and/or certificates, and this
 * function will try to auto-detect based on the key ID the certificate
 * and key pair to use. If the PKCS#12 file contain the issuer of
 * the selected certificate, it will be appended to the certificate
 * to form a chain.
 *
 * If more than one private keys are stored in the PKCS#12 file,
 * then only one key will be read (and it is undefined which one).
 *
 * It is believed that the limitations of this function is acceptable
 * for most usage, and that any more flexibility would introduce
 * complexity that would make it harder to use this functionality at
 * all.
 *
 * Note that, this function by default returns zero on success and a negative value on error.
 * Since 3.5.6, when the flag %GNUTLS_CERTIFICATE_API_V2 is set using gnutls_certificate_set_flags()
 * it returns an index (greater or equal to zero). That index can be used to other functions to refer to the added key-pair.
 *
 * Returns: On success this functions returns zero, and otherwise a negative value on error (see above for modifying that behavior).
 *
 * Since: 2.8.0
 **/
int
 gnutls_certificate_set_x509_simple_pkcs12_mem
    (gnutls_certificate_credentials_t res, const gnutls_datum_t * p12blob,
     gnutls_x509_crt_fmt_t type, const char *password) {
	gnutls_pkcs12_t p12;
	gnutls_x509_privkey_t key = NULL;
	gnutls_x509_crt_t *chain = NULL;
	gnutls_x509_crl_t crl = NULL;
	unsigned int chain_size = 0, i;
	int ret, idx;

	ret = gnutls_pkcs12_init(&p12);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	ret = gnutls_pkcs12_import(p12, p12blob, type, 0);
	if (ret < 0) {
		gnutls_assert();
		gnutls_pkcs12_deinit(p12);
		return ret;
	}

	if (password) {
		ret = gnutls_pkcs12_verify_mac(p12, password);
		if (ret < 0) {
			gnutls_assert();
			gnutls_pkcs12_deinit(p12);
			return ret;
		}
	}

	ret =
	    gnutls_pkcs12_simple_parse(p12, password, &key, &chain,
				       &chain_size, NULL, NULL, &crl, 0);
	gnutls_pkcs12_deinit(p12);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	if (key && chain) {
		ret =
		    gnutls_certificate_set_x509_key(res, chain, chain_size,
						    key);
		if (ret < 0) {
			gnutls_assert();
			goto done;
		}

		idx = ret;
	} else {
		gnutls_assert();
		ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
		goto done;
	}

	if (crl) {
		ret = gnutls_certificate_set_x509_crl(res, &crl, 1);
		if (ret < 0) {
			gnutls_assert();
			goto done;
		}
	}

	if (res->flags & GNUTLS_CERTIFICATE_API_V2)
		ret = idx;
	else
		ret = 0;

      done:
	if (chain) {
		for (i = 0; i < chain_size; i++)
			gnutls_x509_crt_deinit(chain[i]);
		gnutls_free(chain);
	}
	if (key)
		gnutls_x509_privkey_deinit(key);
	if (crl)
		gnutls_x509_crl_deinit(crl);

	return ret;
}