diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php
index b472b8f..f8b4c45 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php
@@ -424,7 +424,7 @@ protected function invokeHook($hook, EntityInterface $entity) {
    * Implements Drupal\Core\Entity\EntityStorageControllerInterface::getQueryServicename().
    */
   public function getQueryServicename() {
-    throw new \LogicException('Querying configuration entities is not supported.');
+    return 'entity.query.config';
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Config/Entity/Query/Condition.php b/core/lib/Drupal/Core/Config/Entity/Query/Condition.php
new file mode 100644
index 0000000..8f80ec6
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/Entity/Query/Condition.php
@@ -0,0 +1,80 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Config\Entity\Query\Condition.
+ */
+
+namespace Drupal\Core\Config\Entity\Query;
+
+use Drupal\Core\Entity\Query\ConditionBase;
+use Drupal\Core\Entity\Query\ConditionInterface;
+use Drupal\Core\Database\Query\SelectInterface;
+use Drupal\Core\Database\Query\Condition as SqlCondition;
+
+class Condition extends ConditionBase {
+
+  /**
+   * Implements Drupal\Core\Entity\Query\ConditionInterface::compile().
+   */
+  public function compile($conditionContainer) {
+    // If this is not the top level condition group then the sql query is
+    // added to the $conditionContainer object by this function itself. The
+    // SQL query object is only necessary to pass to Query::addField() so it
+    // can join tables as necessary. On the other hand, conditions need to be
+    // added to the $conditionContainer object to keep grouping.
+    if ($conditionContainer instanceof SelectInterface) {
+      $added = TRUE;
+      $sqlQuery = $conditionContainer;
+    }
+    else {
+      $added = FALSE;
+      $sqlQuery = $conditionContainer->sqlQuery;
+    }
+
+    foreach ($this->conditions as $condition) {
+      if ($condition['field'] instanceOf ConditionInterface) {
+        $sqlCondition = new SqlCondition($condition['field']->getConjunction());
+        // Add the SQL query to the object before calling this method again.
+        $sqlCondition->sqlQuery = $sqlQuery;
+        $condition['field']->compile($sqlCondition);
+        $sqlQuery->condition($sqlCondition);
+      }
+      else {
+        $and = strtoupper($this->conjunction) == 'AND';
+        $or = !$and;
+        $type = $or || $condition['operator'] == 'IS NULL' ? 'LEFT' : 'INNER';
+        #$this->translateCondition($condition);
+        if ($and || !$added) {
+          $alias = $conditionContainer->join('config_entity_denormalized', NULL, '%alias.entity_type = base_table.entity_type AND %alias.entity_id = base_table.entity_id');
+          $added = TRUE;
+        }
+        if ($and) {
+          $container = $conditionContainer;
+        }
+        else {
+          $container = new SqlCondition('AND');
+        }
+        $container->condition("$alias.name", $condition['field']);
+        $container->condition("$alias.value", $condition['value'], $condition['operator']);
+        if ($or) {
+          $conditionContainer->condition($container);
+        }
+      }
+    }
+  }
+
+  /**
+   * Implements Drupal\Core\Entity\Query\ConditionInterface::exists().
+   */
+  public function exists($field, $langcode = NULL) {
+    return $this->condition($field, NULL, 'IS NOT NULL', $langcode);
+  }
+
+  /**
+   * Implements Drupal\Core\Entity\Query\ConditionInterface::notExists().
+   */
+  public function notExists($field, $langcode = NULL) {
+    return $this->condition($field, NULL, 'IS NULL', $langcode);
+  }
+}
\ No newline at end of file
diff --git a/core/lib/Drupal/Core/Config/Entity/Query/Denormalize.php b/core/lib/Drupal/Core/Config/Entity/Query/Denormalize.php
new file mode 100644
index 0000000..23e4f5b
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/Entity/Query/Denormalize.php
@@ -0,0 +1,105 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Config\Entity\Query\Denormalize.
+ */
+
+namespace Drupal\Core\Config\Entity\Query;
+
+use Drupal\Core\Config\ConfigEvent;
+use Drupal\Core\Database\Connection;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+class Denormalize implements EventSubscriberInterface {
+
+  /**
+   * @var \Drupal\Core\Database\Connection
+   *   The database connection containing the denormalization table.
+   */
+  protected $connection;
+
+  /**
+   * @var string
+   */
+  public $entity_type;
+
+  /**
+   * @var string
+   */
+  protected $entity_id;
+
+  /**
+   * @var \Drupal\Core\Config\Config
+   */
+  protected $config;
+
+  /**
+   * @var \Drupal\Core\Database\Query\Insert
+   */
+  public $insert;
+
+  public function __construct(Connection $connection) {
+    $this->connection = $connection;
+  }
+
+  /**
+   * @param \Drupal\Core\Config\ConfigEvent $event
+   *   The config object being written.
+   */
+  public function configSave(ConfigEvent $event) {
+    $txn = $this->connection->startTransaction();
+    $this->configDelete($event);
+    if ($this->entity_type) {
+      $this->insert = $this->connection->insert('config_entity_denormalized')
+        ->fields(array('entity_type', 'entity_id', 'name', 'value'));
+      $this->values($this->config->get());
+      $this->insert->execute();
+    }
+  }
+
+  public function configDelete(ConfigEvent $event) {
+    $this->config = $event->getConfig();
+    $name = $this->config->getName();
+    if ($this->entity_type = config_get_entity_type_by_name($name)) {
+      $entity_info = entity_get_info($this->entity_type);
+      $this->entity_id = substr($name, strlen($entity_info['config_prefix']) + 1);
+      $this->connection->delete('config_entity_denormalized')
+        ->condition('entity_type', $this->entity_type)
+        ->condition('entity_id', $this->entity_id)
+        ->execute();
+    }
+  }
+
+  /**
+   * @param $data
+   *   The contents of the config object.
+   * @param array $values
+   *   A list of insert values. Each value is a list of $entity_type,
+   *   $entity_id, a flattened config key (for eg.
+   *   display.default.display_title) and the value.
+   * @param string $prefix
+   *   The current config prefix.
+   */
+  protected function values($data, $prefix = '') {
+    foreach ($data as $key => $value) {
+      if (is_array($value)) {
+        $this->values($value, "$prefix$key.");
+      }
+      else {
+        $this->insert->values(array($this->entity_type, $this->entity_id, "$prefix$key", $value));
+      }
+    }
+  }
+
+  /**
+   * Implements \Symfony\Component\EventDispatcher\EventSubscriberInterface::getSubscribedEvents().
+   *
+   * @return array
+   */
+  public static function getSubscribedEvents() {
+    $events['config.save'][] = array('configSave', 20);
+    $events['config.delete'][] = array('configDelete', 20);
+    return $events;
+  }
+}
diff --git a/core/lib/Drupal/Core/Config/Entity/Query/Query.php b/core/lib/Drupal/Core/Config/Entity/Query/Query.php
new file mode 100644
index 0000000..7d9245f
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/Entity/Query/Query.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Drupal\Core\Config\Entity\Query;
+
+use Drupal\Core\Entity\Query\QueryBase;
+
+class Query extends QueryBase {
+  /**
+   * @var \Drupal\Core\Database\Connection
+   */
+  protected $connection;
+
+  /**
+   * @param string $entity_type
+   *   The entity type.
+   * @param string $conjunction
+   *   - AND: all of the conditions on the query need to match.
+   *   - OR: at least one of the conditions on the query need to match.
+   * @param \Drupal\Core\Database\Connection $connection
+   *   The database connection to run the query against.
+   */
+  public function __construct($entity_type, $conjunction, $connection) {
+    parent::__construct($entity_type, $conjunction);
+    $this->connection = $connection;
+  }
+
+  /**
+   * Implements Drupal\Core\Entity\Query\QueryInterface::conditionGroupFactory().
+   */
+  public function conditionGroupFactory($conjunction = 'AND') {
+    return new Condition($conjunction);
+  }
+
+  /**
+   * Implements Drupal\Core\Entity\Query\QueryInterface::execute().
+   */
+  public function execute() {
+    $sqlQuery = $this->connection->select('config_entity_denormalized', 'base_table', array('conjunction' => $this->conjunction));
+    $this->condition->compile($sqlQuery);
+  }
+}
diff --git a/core/lib/Drupal/Core/Config/Entity/Query/QueryFactory.php b/core/lib/Drupal/Core/Config/Entity/Query/QueryFactory.php
new file mode 100644
index 0000000..8cee561
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/Entity/Query/QueryFactory.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Config\Entity\Query\QueryFactory.
+ */
+
+namespace Drupal\Core\Config\Entity\Query;
+
+/**
+ * Factory class creating entity query objects for the SQL backend.
+ */
+class QueryFactory {
+
+  function __construct($connection) {
+    $this->connection = $connection;
+  }
+
+  function get($entity_type, $conjunction = 'AND') {
+    return new Query($entity_type, $conjunction, $this->connection);
+  }
+}
diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
index 2076707..22c7969 100644
--- a/core/lib/Drupal/Core/CoreBundle.php
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -135,9 +135,15 @@ public function build(ContainerBuilder $container) {
     $this->registerTwig($container);
     $this->registerRouting($container);
 
-    // Add the entity query factory.
+    // Add the entity query factories.
     $container->register('entity.query', 'Drupal\Core\Entity\Query\QueryFactory')
       ->addArgument(new Reference('service_container'));
+    $container->register('entity.query.config', 'Drupal\Core\Config\Entity\Query\QueryFactory')
+      ->addArgument(new Reference('database'));
+    $container->register('entity.query.denoramlize', 'Drupal\Core\Config\Entity\Query\Denormalize')
+      ->addArgument(new Reference('database'))
+      ->addTag('event_subscriber');
+
 
     $container->register('router.dumper', 'Drupal\Core\Routing\MatcherDumper')
       ->addArgument(new Reference('database'));
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index b63ca46..8a8a49e 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -678,6 +678,45 @@ function system_schema() {
   $schema['cache_path'] = $schema['cache'];
   $schema['cache_path']['description'] = 'Cache table for path alias lookup.';
 
+  $schema['config_entity_denormalized'] = array(
+    'description' => 'This table is storing denormalized configuration entity objects for query purposes.',
+    'fields' => array(
+      'entity_type' => array(
+        'description' => 'Tne type of the config entity.',
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'entity_id' => array(
+        'description' => 'Tne ID of the config entity.',
+        'type' => 'varchar',
+        'length' => 64,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'name' => array(
+        'description' => 'The key of the key-value pair. As KEY is a SQL reserved keyword, name was chosen instead.',
+        'type' => 'varchar',
+        'length' => 237,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'value' => array(
+        'description' => 'The value.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+    ),
+    'primary key' => array('entity_type', 'entity_id', 'name'),
+    'index' => array(
+      'query_name' => array('entity_type', 'name', array('value', 64)),
+      'query_value' => array('entity_type', array('value', 64), 'name'),
+    ),
+  );
+
   $schema['flood'] = array(
     'description' => 'Flood controls the threshold of events, such as the number of contact attempts.',
     'fields' => array(
