diff --git a/access_vectors b/access_vectors
index 7609d9dc01f498ba5806be525f201d9375ba082a..f8c0110f5ad7d8e83f2e79032cdb844d8aefebea 100644
--- a/access_vectors
+++ b/access_vectors
@@ -893,3 +893,23 @@ class service_manager
 {
 	add
 }
+
+class keystore_key
+{
+	test
+	get
+	insert
+	delete
+	exist
+	saw
+	reset
+	password
+	lock
+	unlock
+	zero
+	sign
+	verify
+	grant
+	duplicate
+	clear_uid
+}
diff --git a/app.te b/app.te
index 63e61e0ff18137720ba973c971e3ed25c9f6e034..b34c52292c3e3748cf30585cc12be3b11dd21a50 100644
--- a/app.te
+++ b/app.te
@@ -174,6 +174,11 @@ read_logd(appdomain)
 # application inherit logd write socket (urge is to deprecate this long term)
 allow appdomain zygote:unix_dgram_socket write;
 
+allow appdomain keystore:keystore_key { test get insert delete exist saw sign verify };
+auditallow appdomain keystore:keystore_key { test get insert delete exist saw sign verify };
+
+use_keystore(appdomain)
+
 ###
 ### Neverallow rules
 ###
diff --git a/binderservicedomain.te b/binderservicedomain.te
index 2533fbef01ee005e5a6974a38d41960325bf7329..3190b6b8a21805aa407316baaecb5745504be8af 100644
--- a/binderservicedomain.te
+++ b/binderservicedomain.te
@@ -16,3 +16,8 @@ allow binderservicedomain appdomain:fifo_file write;
 # Allow binderservicedomain to add services by default.
 allow binderservicedomain service_manager_type:service_manager add;
 auditallow binderservicedomain default_android_service:service_manager add;
+
+allow binderservicedomain keystore:keystore_key { test get insert delete exist saw sign verify };
+auditallow binderservicedomain keystore:keystore_key { test get insert delete exist saw sign verify };
+
+use_keystore(binderservicedomain)
diff --git a/keystore.te b/keystore.te
index 3e627f8270284a53f93e742d42ce670ecbce50da..afa701c7ee46b8eb3255c49ccc945dcbee7d9040 100644
--- a/keystore.te
+++ b/keystore.te
@@ -27,3 +27,6 @@ neverallow { domain -keystore -init -kernel -recovery } keystore_data_file:notde
 neverallow domain keystore:process ptrace;
 
 allow keystore keystore_service:service_manager add;
+
+# Check SELinux permissions.
+selinux_check_access(keystore)
diff --git a/racoon.te b/racoon.te
index 614825540958c810a7b227b2b20d0ea92b325ff0..8b09cdfe4739bb3e917f85ea89aae656f8120ea0 100644
--- a/racoon.te
+++ b/racoon.te
@@ -8,7 +8,6 @@ typeattribute racoon mlstrustedsubject;
 net_domain(racoon)
 
 binder_use(racoon)
-binder_call(racoon, keystore)
 
 allow racoon tun_device:chr_file r_file_perms;
 allow racoon cgroup:dir { add_name create };
@@ -22,3 +21,12 @@ allow racoon self:capability { net_admin net_bind_service net_raw setuid };
 allow racoon system_file:file rx_file_perms;
 allow racoon vpn_data_file:file create_file_perms;
 allow racoon vpn_data_file:dir w_dir_perms;
+
+use_keystore(racoon)
+
+# Racoon (VPN) has a restricted set of permissions from the default.
+allow racoon keystore:keystore_key {
+	get
+	sign
+	verify
+};
diff --git a/security_classes b/security_classes
index 9ff494fdbc00952b99e33dcb27585363f185896b..fcee928e7d5993b5cd3d6aa40f4cfa13ab76d80a 100644
--- a/security_classes
+++ b/security_classes
@@ -140,4 +140,7 @@ class property_service          # userspace
 # Service manager
 class service_manager           # userspace
 
+# Keystore Key
+class keystore_key              # userspace
+
 # FLASK
diff --git a/system_app.te b/system_app.te
index eb5fa9f4cef031e648e657b8678a1bf550ca6ed2..324d74ee69e68be9b39174f4b7603f7b6267cd68 100644
--- a/system_app.te
+++ b/system_app.te
@@ -42,4 +42,40 @@ allow system_app logd_prop:property_service set;
 allow system_app anr_data_file:dir ra_dir_perms;
 allow system_app anr_data_file:file create_file_perms;
 
+allow system_app keystore:keystore_key {
+	test
+	get
+	insert
+	delete
+	exist
+	saw
+	reset
+	password
+	lock
+	unlock
+	zero
+	sign
+	verify
+	grant
+	duplicate
+	clear_uid
+};
+
+auditallow system_app keystore:keystore_key {
+	test
+	get
+	insert
+	delete
+	exist
+	reset
+	password
+	lock
+	unlock
+	sign
+	verify
+	grant
+	duplicate
+	clear_uid
+};
+
 control_logd(system_app)
diff --git a/system_server.te b/system_server.te
index 726ea8c0e421c29ca4aae3441a94f644a54dd2f3..ae7ed570a6f833dc448d3ab8b2a37d354e1e96ae 100644
--- a/system_server.te
+++ b/system_server.te
@@ -359,6 +359,40 @@ allow system_server pstorefs:file r_file_perms;
 
 allow system_server system_server_service:service_manager add;
 
+allow system_server keystore:keystore_key {
+	test
+	get
+	insert
+	delete
+	exist
+	saw
+	reset
+	password
+	lock
+	unlock
+	zero
+	sign
+	verify
+	grant
+	duplicate
+	clear_uid
+};
+
+auditallow system_server keystore:keystore_key {
+	test
+	get
+	insert
+	delete
+	saw
+	lock
+	unlock
+	sign
+	verify
+	grant
+	duplicate
+	clear_uid
+};
+
 ###
 ### Neverallow rules
 ###
diff --git a/te_macros b/te_macros
index c72760eeec16d0a5afe691333b2bd2db0899f341..4199d6e30941027bfba7640e0aaa3267829ee5f5 100644
--- a/te_macros
+++ b/te_macros
@@ -342,3 +342,15 @@ define(`control_logd', `
 # to permit control commands
 unix_socket_connect($1, logd, logd)
 ')
+
+#####################################
+# use_keystore(domain)
+# Ability to use keystore.
+# Keystore is requires the following permissions
+# to call getpidcon.
+define(`use_keystore', `
+  allow keystore $1:dir search;
+  allow keystore $1:file { read open };
+  allow keystore $1:process getattr;
+  binder_call($1, keystore)
+')
diff --git a/wpa.te b/wpa.te
index 761d3451a2e1ec3915694a76f0d78eec2a0024de..7b1a8751d6faa56eff5b522a2a02f8ff07e5fdb6 100644
--- a/wpa.te
+++ b/wpa.te
@@ -17,13 +17,21 @@ allow wpa wifi_data_file:file create_file_perms;
 unix_socket_send(wpa, system_wpa, system_server)
 
 binder_use(wpa)
-binder_call(wpa, keystore)
 
 # Create a socket for receiving info from wpa
 type_transition wpa wifi_data_file:dir wpa_socket "sockets";
 allow wpa wpa_socket:dir create_dir_perms;
 allow wpa wpa_socket:sock_file create_file_perms;
 
+use_keystore(wpa)
+
+# WPA (wifi) has a restricted set of permissions from the default.
+allow wpa keystore:keystore_key {
+	get
+	sign
+	verify
+};
+
 # Allow wpa_cli to work. wpa_cli creates a socket in
 # /data/misc/wifi/sockets which wpa supplicant communicates with.
 userdebug_or_eng(`