Merge branch 'x86-cpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[firefly-linux-kernel-4.4.55.git] / crypto / asymmetric_keys / asymmetric_type.c
index f0f2111d2c668b29ae58ad42fcea1ffea364a9bd..bcbbbd794e1da209d519baca7de8b0ddf1115716 100644 (file)
@@ -65,23 +65,44 @@ bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1,
 }
 EXPORT_SYMBOL_GPL(asymmetric_key_id_same);
 
+/**
+ * asymmetric_key_id_partial - Return true if two asymmetric keys IDs
+ * partially match
+ * @kid_1, @kid_2: The key IDs to compare
+ */
+bool asymmetric_key_id_partial(const struct asymmetric_key_id *kid1,
+                              const struct asymmetric_key_id *kid2)
+{
+       if (!kid1 || !kid2)
+               return false;
+       if (kid1->len < kid2->len)
+               return false;
+       return memcmp(kid1->data + (kid1->len - kid2->len),
+                     kid2->data, kid2->len) == 0;
+}
+EXPORT_SYMBOL_GPL(asymmetric_key_id_partial);
+
 /**
  * asymmetric_match_key_ids - Search asymmetric key IDs
  * @kids: The list of key IDs to check
  * @match_id: The key ID we're looking for
+ * @match: The match function to use
  */
-bool asymmetric_match_key_ids(const struct asymmetric_key_ids *kids,
-                             const struct asymmetric_key_id *match_id)
+static bool asymmetric_match_key_ids(
+       const struct asymmetric_key_ids *kids,
+       const struct asymmetric_key_id *match_id,
+       bool (*match)(const struct asymmetric_key_id *kid1,
+                     const struct asymmetric_key_id *kid2))
 {
+       int i;
+
        if (!kids || !match_id)
                return false;
-       if (asymmetric_key_id_same(kids->id[0], match_id))
-               return true;
-       if (asymmetric_key_id_same(kids->id[1], match_id))
-               return true;
+       for (i = 0; i < ARRAY_SIZE(kids->id); i++)
+               if (match(kids->id[i], match_id))
+                       return true;
        return false;
 }
-EXPORT_SYMBOL_GPL(asymmetric_match_key_ids);
 
 /**
  * asymmetric_key_hex_to_key_id - Convert a hex string into a key ID.
@@ -113,7 +134,7 @@ struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id)
 }
 
 /*
- * Match asymmetric keys by ID.
+ * Match asymmetric keys by an exact match on an ID.
  */
 static bool asymmetric_key_cmp(const struct key *key,
                               const struct key_match_data *match_data)
@@ -121,7 +142,21 @@ static bool asymmetric_key_cmp(const struct key *key,
        const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
        const struct asymmetric_key_id *match_id = match_data->preparsed;
 
-       return asymmetric_match_key_ids(kids, match_id);
+       return asymmetric_match_key_ids(kids, match_id,
+                                       asymmetric_key_id_same);
+}
+
+/*
+ * Match asymmetric keys by a partial match on an IDs.
+ */
+static bool asymmetric_key_cmp_partial(const struct key *key,
+                                      const struct key_match_data *match_data)
+{
+       const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
+       const struct asymmetric_key_id *match_id = match_data->preparsed;
+
+       return asymmetric_match_key_ids(kids, match_id,
+                                       asymmetric_key_id_partial);
 }
 
 /*
@@ -131,7 +166,8 @@ static bool asymmetric_key_cmp(const struct key *key,
  * There are some specifiers for matching key IDs rather than by the key
  * description:
  *
- *     "id:<id>" - request a key by any available ID
+ *     "id:<id>" - find a key by partial match on any available ID
+ *     "ex:<id>" - find a key by exact match on any available ID
  *
  * These have to be searched by iteration rather than by direct lookup because
  * the key is hashed according to its description.
@@ -141,6 +177,8 @@ static int asymmetric_key_match_preparse(struct key_match_data *match_data)
        struct asymmetric_key_id *match_id;
        const char *spec = match_data->raw_data;
        const char *id;
+       bool (*cmp)(const struct key *, const struct key_match_data *) =
+               asymmetric_key_cmp;
 
        if (!spec || !*spec)
                return -EINVAL;
@@ -148,16 +186,21 @@ static int asymmetric_key_match_preparse(struct key_match_data *match_data)
            spec[1] == 'd' &&
            spec[2] == ':') {
                id = spec + 3;
+               cmp = asymmetric_key_cmp_partial;
+       } else if (spec[0] == 'e' &&
+                  spec[1] == 'x' &&
+                  spec[2] == ':') {
+               id = spec + 3;
        } else {
                goto default_match;
        }
 
        match_id = asymmetric_key_hex_to_key_id(id);
-       if (!match_id)
-               return -ENOMEM;
+       if (IS_ERR(match_id))
+               return PTR_ERR(match_id);
 
        match_data->preparsed = match_id;
-       match_data->cmp = asymmetric_key_cmp;
+       match_data->cmp = cmp;
        match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE;
        return 0;
 
@@ -190,14 +233,14 @@ static void asymmetric_key_describe(const struct key *key, struct seq_file *m)
                seq_puts(m, ": ");
                subtype->describe(key, m);
 
-               if (kids && kids->id[0]) {
-                       kid = kids->id[0];
+               if (kids && kids->id[1]) {
+                       kid = kids->id[1];
                        seq_putc(m, ' ');
                        n = kid->len;
                        p = kid->data;
-                       if (n > 8) {
-                               p += n - 8;
-                               n = 8;
+                       if (n > 4) {
+                               p += n - 4;
+                               n = 4;
                        }
                        seq_printf(m, "%*phN", n, p);
                }
@@ -251,6 +294,7 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
 {
        struct asymmetric_key_subtype *subtype = prep->type_data[0];
        struct asymmetric_key_ids *kids = prep->type_data[1];
+       int i;
 
        pr_devel("==>%s()\n", __func__);
 
@@ -259,8 +303,8 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
                module_put(subtype->owner);
        }
        if (kids) {
-               kfree(kids->id[0]);
-               kfree(kids->id[1]);
+               for (i = 0; i < ARRAY_SIZE(kids->id); i++)
+                       kfree(kids->id[i]);
                kfree(kids);
        }
        kfree(prep->description);