diff --git a/core/includes/entity.api.php b/core/includes/entity.api.php
index e6e1f7cde65481d760a924e415cc5bc7f6aa8f81..8c2c240f137f00147d09ea82bf987e5564c542eb 100644
--- a/core/includes/entity.api.php
+++ b/core/includes/entity.api.php
@@ -10,6 +10,86 @@
  * @{
  */
 
+/**
+ * Control entity operation access.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ *   The entity to check access to.
+ * @param string $operation
+ *   The operation that is to be performed on $entity.
+ * @param \Drupal\Core\Session\AccountInterface $account
+ *    The account trying to access the entity.
+ * @param string $langcode
+ *    The code of the language $entity is accessed in.
+ *
+ * @return bool|null
+ *   A boolean to explicitly allow or deny access, or NULL to neither allow nor
+ *   deny access.
+ *
+ * @see \Drupal\Core\Entity\EntityAccessController
+ */
+function hook_entity_access(\Drupal\Core\Entity\EntityInterface $entity, $operation, \Drupal\Core\Session\AccountInterface $account, $langcode) {
+  return NULL;
+}
+
+/**
+ * Control entity operation access for a specific entity type.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ *   The entity to check access to.
+ * @param string $operation
+ *   The operation that is to be performed on $entity.
+ * @param \Drupal\Core\Session\AccountInterface $account
+ *    The account trying to access the entity.
+ * @param string $langcode
+ *    The code of the language $entity is accessed in.
+ *
+ * @return bool|null
+ *   A boolean to explicitly allow or deny access, or NULL to neither allow nor
+ *   deny access.
+ *
+ * @see \Drupal\Core\Entity\EntityAccessController
+ */
+function hook_ENTITY_TYPE_access(\Drupal\Core\Entity\EntityInterface $entity, $operation, \Drupal\Core\Session\AccountInterface $account, $langcode) {
+  return NULL;
+}
+
+/**
+ * Control entity create access.
+ *
+ * @param \Drupal\Core\Session\AccountInterface $account
+ *    The account trying to access the entity.
+ * @param string $langcode
+ *    The code of the language $entity is accessed in.
+ *
+ * @return bool|null
+ *   A boolean to explicitly allow or deny access, or NULL to neither allow nor
+ *   deny access.
+ *
+ * @see \Drupal\Core\Entity\EntityAccessController
+ */
+function hook_entity_create_access(\Drupal\Core\Session\AccountInterface $account, $langcode) {
+  return NULL;
+}
+
+/**
+ * Control entity create access for a specific entity type.
+ *
+ * @param \Drupal\Core\Session\AccountInterface $account
+ *    The account trying to access the entity.
+ * @param string $langcode
+ *    The code of the language $entity is accessed in.
+ *
+ * @return bool|null
+ *   A boolean to explicitly allow or deny access, or NULL to neither allow nor
+ *   deny access.
+ *
+ * @see \Drupal\Core\Entity\EntityAccessController
+ */
+function hook_ENTITY_TYPE_create_access(\Drupal\Core\Session\AccountInterface $account, $langcode) {
+  return NULL;
+}
+
 /**
  * Add to entity type definitions.
  *
diff --git a/core/lib/Drupal/Core/Entity/EntityAccessController.php b/core/lib/Drupal/Core/Entity/EntityAccessController.php
index 47573c20a6c12b7bd8bbf8937d0cc704553f7704..5583aecb09648a6c9f692eed873240059620452c 100644
--- a/core/lib/Drupal/Core/Entity/EntityAccessController.php
+++ b/core/lib/Drupal/Core/Entity/EntityAccessController.php
@@ -44,7 +44,7 @@ class EntityAccessController implements EntityAccessControllerInterface {
    *   The entity type of the access controller instance.
    */
   public function __construct($entity_type) {
-    $this->entity_type = $entity_type;
+    $this->entityType = $entity_type;
   }
 
   /**
@@ -58,15 +58,19 @@ public function access(EntityInterface $entity, $operation, $langcode = Language
       return $access;
     }
 
-    // Invoke hook_entity_access(), hook results take precedence over overridden
-    // implementations of EntityAccessController::checkAccess(). Entities
-    // that have checks that need to be done before the hook is invoked should
-    // do so by overridding this method.
+    // Invoke hook_entity_access() and hook_ENTITY_TYPE_access(). Hook results
+    // take precedence over overridden implementations of
+    // EntityAccessController::checkAccess(). Entities that have checks that
+    // need to be done before the hook is invoked should do so by overriding
+    // this method.
 
     // We grant access to the entity if both of these conditions are met:
     // - No modules say to deny access.
     // - At least one module says to grant access.
-    $access = $this->moduleHandler->invokeAll($entity->entityType() . '_access', array($entity, $operation, $account, $langcode));
+    $access = array_merge(
+      $this->moduleHandler->invokeAll('entity_access', array($entity, $operation, $account, $langcode)),
+      $this->moduleHandler->invokeAll($entity->entityType() . '_access', array($entity, $operation, $account, $langcode))
+    );
 
     if (($return = $this->processAccessHookResults($access)) === NULL) {
       // No module had an opinion about the access, so let's the access
@@ -196,15 +200,19 @@ public function createAccess($entity_bundle = NULL, AccountInterface $account =
       return $access;
     }
 
-    // Invoke hook_entity_access(), hook results take precedence over overridden
-    // implementations of EntityAccessController::checkAccess(). Entities
-    // that have checks that need to be done before the hook is invoked should
-    // do so by overridding this method.
+    // Invoke hook_entity_create_access() and hook_ENTITY_TYPE_create_access().
+    // Hook results take precedence over overridden implementations of
+    // EntityAccessController::checkAccess(). Entities that have checks that
+    // need to be done before the hook is invoked should do so by overriding
+    // this method.
 
     // We grant access to the entity if both of these conditions are met:
     // - No modules say to deny access.
     // - At least one module says to grant access.
-    $access = $this->moduleHandler->invokeAll($this->entity_type . '_create_access', array($account, $context['langcode']));
+    $access = array_merge(
+      $this->moduleHandler->invokeAll('entity_create_access', array($account, $context['langcode'])),
+      $this->moduleHandler->invokeAll($this->entityType . '_create_access', array($account, $context['langcode']))
+    );
 
     if (($return = $this->processAccessHookResults($access)) === NULL) {
       // No module had an opinion about the access, so let's the access
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php
index 440d2d0a46f90fd6e5870bed98f3d5740007038d..33b2c1a7eb9d8e3e6d5922231e77ff89bd5b0e06 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php
@@ -135,4 +135,24 @@ function testEntityTranslationAccess() {
       'view' => TRUE,
     ), $translation);
   }
+
+  /**
+   * Tests hook invocations.
+   */
+  protected function testHooks() {
+    $state = $this->container->get('state');
+    $entity = entity_create('entity_test', array(
+      'name' => 'test',
+    ));
+
+    // Test hook_entity_create_access() and hook_ENTITY_TYPE_create_access().
+    $entity->access('create');
+    $this->assertEqual($state->get('entity_test_entity_create_access'), TRUE);
+    $this->assertEqual($state->get('entity_test_entity_test_create_access'), TRUE);
+
+    // Test hook_entity_access() and hook_ENTITY_TYPE_access().
+    $entity->access('view');
+    $this->assertEqual($state->get('entity_test_entity_access'), TRUE);
+    $this->assertEqual($state->get('entity_test_entity_test_access'), TRUE);
+  }
 }
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module
index 6e2082a4c12c2acc900228c91db0b48c968ed9af..4ef754d7b3ab76d6ad959f9ccb151a7f89335d0e 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.module
+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -6,6 +6,7 @@
  */
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Session\AccountInterface;
 use Drupal\entity\Entity\EntityFormDisplay;
 use Drupal\field\Entity\Field;
 use Drupal\field\Entity\FieldInstance;
@@ -529,3 +530,31 @@ function entity_test_entity_prepare_view($entity_type, array $entities, array $d
     }
   }
 }
+
+/**
+ * Implements hook_entity_access().
+ */
+function entity_test_entity_access(EntityInterface $entity, $operation, AccountInterface $account, $langcode) {
+  \Drupal::state()->set('entity_test_entity_access', TRUE);
+}
+
+/**
+ * Implements hook_ENTITY_TYPE_access().
+ */
+function entity_test_entity_test_access(EntityInterface $entity, $operation, AccountInterface $account, $langcode) {
+  \Drupal::state()->set('entity_test_entity_test_access', TRUE);
+}
+
+/**
+ * Implements hook_entity_create_access().
+ */
+function entity_test_entity_create_access(AccountInterface $account, $langcode) {
+  \Drupal::state()->set('entity_test_entity_create_access', TRUE);
+}
+
+/**
+ * Implements hook_ENTITY_TYPE_create_access().
+ */
+function entity_test_entity_test_create_access(AccountInterface $account, $langcode) {
+  \Drupal::state()->set('entity_test_entity_test_create_access', TRUE);
+}