diff --git a/introspection/nm-device-wifi.xml b/introspection/nm-device-wifi.xml
index 21ace0a..5fe782d 100644
--- a/introspection/nm-device-wifi.xml
+++ b/introspection/nm-device-wifi.xml
@@ -14,6 +14,18 @@
       </tp:docstring>
     </method>
 
+    <method name="ProbeCaCert">
+      <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_device_probe_ca_cert"/>
+      <arg name="ssid" type="ay" direction="in">
+        <tp:docstring>
+          The SSID of the AP to be probed
+        </tp:docstring>
+      </arg>
+      <tp:docstring>
+        Probe the CA certificate of the RADIUS server.
+      </tp:docstring>
+    </method>
+
     <property name="HwAddress" type="s" access="read">
       <tp:docstring>
         The hardware address of the device.
@@ -74,6 +86,17 @@
         </tp:docstring>
     </signal>
 
+    <signal name="CaCertReceived">
+      <arg name="cert" type="a{ss}" tp:type="String_String_Map">
+        <tp:docstring>
+          The certificate of the RADIUS server
+        </tp:docstring>
+      </arg>
+        <tp:docstring>
+            Emitted when wpa_supplicant replies the CA certificate of the RADIUS server.
+        </tp:docstring>
+    </signal>
+
     <tp:flags name="NM_802_11_DEVICE_CAP" type="u">
       <tp:docstring>
         Flags describing the capabilities of a wireless device.
diff --git a/libnm-glib/libnm_glib.ver b/libnm-glib/libnm_glib.ver
index 3ba54d6..23599e4 100644
--- a/libnm-glib/libnm_glib.ver
+++ b/libnm-glib/libnm_glib.ver
@@ -80,6 +80,7 @@ global:
 	nm_device_wifi_get_mode;
 	nm_device_wifi_get_type;
 	nm_device_wifi_new;
+	nm_device_wifi_probe_ca_cert;
 	nm_dhcp4_config_get_one_option;
 	nm_dhcp4_config_get_options;
 	nm_dhcp4_config_get_type;
diff --git a/libnm-glib/nm-device-wifi.c b/libnm-glib/nm-device-wifi.c
index 1729c8a..3b988bb 100644
--- a/libnm-glib/nm-device-wifi.c
+++ b/libnm-glib/nm-device-wifi.c
@@ -75,6 +75,7 @@ enum {
 enum {
 	ACCESS_POINT_ADDED,
 	ACCESS_POINT_REMOVED,
+	CA_CERT_RECEIVED,
 
 	LAST_SIGNAL
 };
@@ -341,6 +342,25 @@ nm_device_wifi_get_access_point_by_path (NMDeviceWifi *device,
 	return ap;
 }
 
+gboolean
+nm_device_wifi_probe_ca_cert (NMDeviceWifi *device,
+                              const GByteArray *ssid)
+{
+	NMDeviceWifiPrivate *priv;
+	GError *error = NULL;
+
+	g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), FALSE);
+
+	priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
+
+	if (!org_freedesktop_NetworkManager_Device_Wireless_probe_ca_cert (priv->proxy, ssid, &error)) {
+		g_warning ("%s: error probe subject: %s", __func__, error->message);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 static void
 access_point_added_proxy (DBusGProxy *proxy, char *path, gpointer user_data)
 {
@@ -396,6 +416,15 @@ access_point_removed_proxy (DBusGProxy *proxy, char *path, gpointer user_data)
 	}
 }
 
+
+static void
+ca_cert_received_proxy (DBusGProxy *proxy, GHashTable *ca_cert, gpointer user_data)
+{
+	NMDeviceWifi *self = NM_DEVICE_WIFI (user_data);
+
+	g_signal_emit (self, signals[CA_CERT_RECEIVED], 0, ca_cert);
+}
+
 static void
 clean_up_aps (NMDeviceWifi *self, gboolean notify)
 {
@@ -602,6 +631,13 @@ constructor (GType type,
 						    G_CALLBACK (access_point_removed_proxy),
 						    object, NULL);
 
+	dbus_g_proxy_add_signal (priv->proxy, "CaCertReceived",
+	                         DBUS_TYPE_G_MAP_OF_STRING,
+	                         G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (priv->proxy, "CaCertReceived",
+						    G_CALLBACK (ca_cert_received_proxy),
+						    object, NULL);
+
 	register_for_property_changed (NM_DEVICE_WIFI (object));
 
 	g_signal_connect (NM_DEVICE (object),
@@ -756,4 +792,22 @@ nm_device_wifi_class_init (NMDeviceWifiClass *device_class)
 				    g_cclosure_marshal_VOID__OBJECT,
 				    G_TYPE_NONE, 1,
 				    G_TYPE_OBJECT);
+
+	/**
+	 * NMDeviceWifi::ca-cert-received:
+	 * @device: the wifi device that received the signal
+	 * @subject: the subject of the RADIUS server
+	 * @hash: the hash of the RADIUS server
+	 *
+	 * Notifies that a certificate of a RADIUS server is sent back.
+	 **/
+	signals[CA_CERT_RECEIVED] =
+		g_signal_new ("ca-cert-received",
+				    G_OBJECT_CLASS_TYPE (object_class),
+				    G_SIGNAL_RUN_FIRST,
+				    G_STRUCT_OFFSET (NMDeviceWifiClass, ca_cert_received),
+				    NULL, NULL,
+				    g_cclosure_marshal_VOID__BOXED,
+				    G_TYPE_NONE, 1,
+				    G_TYPE_HASH_TABLE);
 }
diff --git a/libnm-glib/nm-device-wifi.h b/libnm-glib/nm-device-wifi.h
index 69e6dd7..f594476 100644
--- a/libnm-glib/nm-device-wifi.h
+++ b/libnm-glib/nm-device-wifi.h
@@ -52,6 +52,7 @@ typedef struct {
 	/* Signals */
 	void (*access_point_added) (NMDeviceWifi *device, NMAccessPoint *ap);
 	void (*access_point_removed) (NMDeviceWifi *device, NMAccessPoint *ap);
+	void (*ca_cert_received) (NMDeviceWifi *device, GHashTable *ca_cert);
 } NMDeviceWifiClass;
 
 GType nm_device_wifi_get_type (void);
@@ -68,6 +69,8 @@ NMAccessPoint * nm_device_wifi_get_access_point_by_path (NMDeviceWifi *device,
                                                          const char *path);
 
 const GPtrArray *nm_device_wifi_get_access_points       (NMDeviceWifi *device);
+gboolean         nm_device_wifi_probe_ca_cert           (NMDeviceWifi *device,
+                                                         const GByteArray *ssid);
 
 G_END_DECLS
 
diff --git a/libnm-util/nm-setting-8021x.h b/libnm-util/nm-setting-8021x.h
index 140ea2d..3dcf111 100644
--- a/libnm-util/nm-setting-8021x.h
+++ b/libnm-util/nm-setting-8021x.h
@@ -93,6 +93,7 @@ GQuark nm_setting_802_1x_error_quark (void);
 
 #define NM_SETTING_802_1X_CK_FORMAT_ID   "id:"
 #define NM_SETTING_802_1X_CK_FORMAT_FILE "file:"
+#define NM_SETTING_802_1X_CK_FORMAT_HASH "hash://server/sha256/"
 
 typedef struct {
 	NMSetting parent;
diff --git a/marshallers/nm-marshal.list b/marshallers/nm-marshal.list
index 5dc958a..bfd09b5 100644
--- a/marshallers/nm-marshal.list
+++ b/marshallers/nm-marshal.list
@@ -17,4 +17,6 @@ VOID:STRING,INT
 VOID:STRING,UINT
 VOID:OBJECT,OBJECT,ENUM
 VOID:POINTER,STRING
+VOID:INT,STRING,STRING
+VOID:INT,STRING,STRING,BOXED
 POINTER:POINTER
diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c
index 3cddaab..b043c76 100644
--- a/src/nm-device-wifi.c
+++ b/src/nm-device-wifi.c
@@ -37,6 +37,7 @@
 #include "nm-device-interface.h"
 #include "nm-device-private.h"
 #include "nm-utils.h"
+#include "nm-marshal.h"
 #include "NetworkManagerUtils.h"
 #include "NetworkManagerPolicy.h"
 #include "nm-activation-request.h"
@@ -51,10 +52,14 @@
 #include "nm-setting-ip4-config.h"
 #include "nm-setting-ip6-config.h"
 #include "NetworkManagerSystem.h"
+#include "nm-dbus-glib-types.h"
 
 static gboolean impl_device_get_access_points (NMDeviceWifi *device,
                                                GPtrArray **aps,
                                                GError **err);
+static gboolean impl_device_probe_ca_cert (NMDeviceWifi *device,
+                                           GByteArray *ssid,
+                                           GError **err);
 
 #include "nm-device-wifi-glue.h"
 
@@ -90,6 +95,7 @@ enum {
 	ACCESS_POINT_REMOVED,
 	HIDDEN_AP_FOUND,
 	PROPERTIES_CHANGED,
+	CA_CERT_RECEIVED,
 
 	LAST_SIGNAL
 };
@@ -100,6 +106,7 @@ typedef enum {
 	NM_WIFI_ERROR_CONNECTION_NOT_WIRELESS = 0,
 	NM_WIFI_ERROR_CONNECTION_INVALID,
 	NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE,
+	NM_WIFI_ERROR_INVALID_CA_PROBE,
 } NMWifiError;
 
 #define NM_WIFI_ERROR (nm_wifi_error_quark ())
@@ -125,6 +132,7 @@ typedef struct Supplicant {
 	guint iface_scan_request_result_id;
 	guint iface_scan_results_id;
 	guint iface_con_state_id;
+	guint iface_cert_id;
 
 	/* Timeouts and idles */
 	guint iface_con_error_cb_id;
@@ -244,6 +252,8 @@ nm_wifi_error_get_type (void)
 			ENUM_ENTRY (NM_WIFI_ERROR_CONNECTION_INVALID, "ConnectionInvalid"),
 			/* Connection does not apply to this device. */
 			ENUM_ENTRY (NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE, "ConnectionIncompatible"),
+			/* CA Probe was not valid. */
+			ENUM_ENTRY (NM_WIFI_ERROR_INVALID_CA_PROBE, "InvalidCaProbe"),
 			{ 0, 0, 0 }
 		};
 		etype = g_enum_register_static ("NMWifiError", values);
@@ -1305,6 +1315,85 @@ impl_device_get_access_points (NMDeviceWifi *self,
 	return TRUE;
 }
 
+static void
+supplicant_iface_certification_cb (NMSupplicantInterface * iface,
+                                   const gint   depth,
+                                   const char * subject,
+                                   const char * hash,
+                                   NMDeviceWifi * self)
+{
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+	GHashTable *ca_cert;
+	char *data;
+
+	nm_info ("Got Server Certificate: depth %d, subject %s, hash %s", depth, subject, hash);
+
+	if (depth != 0)
+		return;
+
+	ca_cert = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
+	if (subject) {
+		data = g_strdup (subject);
+		g_hash_table_insert (ca_cert, "subject", data);
+	}
+	if (hash) {
+		data = g_strdup (hash);
+		g_hash_table_insert (ca_cert, "hash", data);
+	}
+
+	g_signal_emit (self, signals[CA_CERT_RECEIVED], 0, ca_cert);
+
+	g_hash_table_destroy (ca_cert);
+
+	if (priv->supplicant.iface_cert_id > 0) {
+		g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_cert_id);
+		priv->supplicant.iface_cert_id = 0;
+	}
+
+	nm_supplicant_interface_disconnect (iface);
+}
+
+static gboolean
+impl_device_probe_ca_cert (NMDeviceWifi *self,
+                           GByteArray *ssid,
+                           GError **err)
+{
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+	NMSupplicantConfig *config = NULL;
+	guint id;
+	gboolean ret = FALSE;
+
+	config = nm_supplicant_config_probe_new (ssid);
+	if (!config)
+		goto error;
+
+	/* Hook up signal handler to capture certification signal */
+	id = g_signal_connect (priv->supplicant.iface,
+	                       "certification",
+	                       G_CALLBACK (supplicant_iface_certification_cb),
+	                       self);
+	priv->supplicant.iface_cert_id = id;
+
+	if (!nm_supplicant_interface_set_config (priv->supplicant.iface, config))
+		goto error;
+
+	ret = TRUE;
+
+error:
+	if (!ret) {
+		g_set_error_literal (err,
+		                     NM_WIFI_ERROR,
+		                     NM_WIFI_ERROR_INVALID_CA_PROBE,
+		                     "Couldn't probe CA Certificate");
+		if (priv->supplicant.iface_cert_id) {
+			g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_cert_id);
+			priv->supplicant.iface_cert_id = 0;
+		}
+	}
+
+	return ret;
+}
+
 /*
  * nm_device_get_mode
  *
@@ -3400,6 +3489,16 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
 		nm_properties_changed_signal_new (object_class,
 		                                  G_STRUCT_OFFSET (NMDeviceWifiClass, properties_changed));
 
+	signals[CA_CERT_RECEIVED] =
+		g_signal_new ("ca-cert-received",
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_FIRST,
+		              G_STRUCT_OFFSET (NMDeviceWifiClass, ca_cert_received),
+		              NULL, NULL,
+		              g_cclosure_marshal_VOID__BOXED,
+		              G_TYPE_NONE, 1,
+		              DBUS_TYPE_G_MAP_OF_STRING);
+
 	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), &dbus_glib_nm_device_wifi_object_info);
 
 	dbus_g_error_domain_register (NM_WIFI_ERROR, NULL, NM_TYPE_WIFI_ERROR);
diff --git a/src/nm-device-wifi.h b/src/nm-device-wifi.h
index 1e885cb..0fa9e3f 100644
--- a/src/nm-device-wifi.h
+++ b/src/nm-device-wifi.h
@@ -73,6 +73,7 @@ struct _NMDeviceWifiClass
 	void (*access_point_removed) (NMDeviceWifi *device, NMAccessPoint *ap);
 	void (*hidden_ap_found)      (NMDeviceWifi *device, NMAccessPoint *ap);
 	void (*properties_changed)   (NMDeviceWifi *device, GHashTable *properties);
+	void (*ca_cert_received)     (NMDeviceWifi *device, GHashTable *ca_cert);
 };
 
 
diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c
index 274b3f0..141f469 100644
--- a/src/supplicant-manager/nm-supplicant-config.c
+++ b/src/supplicant-manager/nm-supplicant-config.c
@@ -179,6 +179,25 @@ nm_supplicant_config_add_option (NMSupplicantConfig *self,
 	return nm_supplicant_config_add_option_with_type (self, key, value, len, TYPE_INVALID, secret);
 }
 
+NMSupplicantConfig *
+nm_supplicant_config_probe_new (GByteArray *ssid)
+{
+	NMSupplicantConfig *probe_config;
+
+	if (!ssid)
+		return NULL;
+
+	probe_config = (NMSupplicantConfig *)g_object_new (NM_TYPE_SUPPLICANT_CONFIG, NULL);
+
+	nm_supplicant_config_add_option (probe_config, "ssid", (char *)ssid->data, ssid->len, FALSE);
+	nm_supplicant_config_add_option (probe_config, "key_mgmt", "WPA-EAP", -1, FALSE);
+	nm_supplicant_config_add_option (probe_config, "eap", "TTLS PEAP TLS", -1, FALSE);
+	nm_supplicant_config_add_option (probe_config, "identity", " ", -1, FALSE);
+	nm_supplicant_config_add_option (probe_config, "ca_cert", "probe://", -1, FALSE);
+
+	return probe_config;
+}
+
 static gboolean
 nm_supplicant_config_add_blob (NMSupplicantConfig *self,
                                const char *key,
@@ -795,6 +814,10 @@ add_certificates (NMSupplicantConfig *self, NMSetting8021x *setting, const char
 				nm_supplicant_config_add_option (self, "ca_cert",
 												 str + strlen (NM_SETTING_802_1X_CK_FORMAT_FILE),
 												 -1, FALSE);
+			else if (g_str_has_prefix (str, NM_SETTING_802_1X_CK_FORMAT_HASH))
+				nm_supplicant_config_add_option (self, "ca_cert",
+												 str,
+												 -1, FALSE);
 			else {
 				ADD_BLOB_VAL (array, "ca_cert", connection_uid);
 			}
diff --git a/src/supplicant-manager/nm-supplicant-config.h b/src/supplicant-manager/nm-supplicant-config.h
index 68779bd..0337653 100644
--- a/src/supplicant-manager/nm-supplicant-config.h
+++ b/src/supplicant-manager/nm-supplicant-config.h
@@ -52,6 +52,8 @@ GType nm_supplicant_config_get_type (void);
 
 NMSupplicantConfig *nm_supplicant_config_new (void);
 
+NMSupplicantConfig *nm_supplicant_config_probe_new (GByteArray *ssid);
+
 guint32 nm_supplicant_config_get_ap_scan (NMSupplicantConfig *self);
 
 void nm_supplicant_config_set_ap_scan (NMSupplicantConfig *self,
diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c
index 7f94fab..02d6400 100644
--- a/src/supplicant-manager/nm-supplicant-interface.c
+++ b/src/supplicant-manager/nm-supplicant-interface.c
@@ -80,6 +80,7 @@ enum {
 	SCAN_RESULTS,      /* scan results returned from supplicant */
 	CONNECTION_STATE,  /* link state of the device's connection */
 	CONNECTION_ERROR,  /* an error occurred during a connection request */
+	CERTIFICATION,     /* Got RADIUS server certificate */
 	LAST_SIGNAL
 };
 static guint nm_supplicant_interface_signals[LAST_SIGNAL] = { 0 };
@@ -497,6 +498,14 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass)
 		              NULL, NULL,
 		              _nm_marshal_VOID__STRING_STRING,
 		              G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);
+	nm_supplicant_interface_signals[CERTIFICATION] =
+		g_signal_new ("certification",
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              G_STRUCT_OFFSET (NMSupplicantInterfaceClass, certification),
+		              NULL, NULL,
+		              _nm_marshal_VOID__INT_STRING_STRING,
+		              G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING);
 }
 
 static void
@@ -790,6 +799,22 @@ nm_supplicant_interface_get_scanning (NMSupplicantInterface *self)
 }
 
 static void
+wpas_iface_handle_certification (DBusGProxy      *proxy,
+                                 const int        depth,
+                                 const char      *str_subject,
+                                 const char      *str_hash,
+				 const GPtrArray *cert_hex_array,
+                                 gpointer user_data)
+{
+	g_signal_emit (user_data,
+	               nm_supplicant_interface_signals[CERTIFICATION],
+	               0,
+	               depth,
+	               str_subject,
+	               str_hash);
+}
+
+static void
 nm_supplicant_interface_add_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
 {
 	NMSupplicantInfo *info = (NMSupplicantInfo *) user_data;
@@ -847,6 +872,17 @@ nm_supplicant_interface_add_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpoi
 		                             info->interface,
 		                             NULL);
 
+		dbus_g_object_register_marshaller (_nm_marshal_VOID__INT_STRING_STRING_BOXED,
+		                                   G_TYPE_NONE,
+		                                   G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, DBUS_TYPE_G_UCHAR_ARRAY,
+		                                   G_TYPE_INVALID);
+		dbus_g_proxy_add_signal (priv->iface_proxy, "Certification", G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_INVALID);
+
+		dbus_g_proxy_connect_signal (priv->iface_proxy, "Certification",
+		                             G_CALLBACK (wpas_iface_handle_certification),
+		                             info->interface,
+		                             NULL);
+
 		/* Interface added to the supplicant; get its initial state. */
 		wpas_iface_get_state (info->interface);
 		wpas_iface_get_scanning (info->interface);
diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h
index e6b52f7..8a87a2d 100644
--- a/src/supplicant-manager/nm-supplicant-interface.h
+++ b/src/supplicant-manager/nm-supplicant-interface.h
@@ -112,6 +112,12 @@ typedef struct {
 	void (*connection_error) (NMSupplicantInterface * iface,
 	                          const char * name,
 	                          const char * message);
+
+	/* got the RADIUS server certificate */
+	void (*certification) (NMSupplicantInterface * iface,
+	                       const gint   depth,
+	                       const char * subject,
+	                       const char * hash);
 } NMSupplicantInterfaceClass;
 
 
