bfb0424026aa3c7047679c8df9fa15663dce0e3d
[linux-3.10.git] / crypto / asymmetric_keys / asymmetric_type.c
1 /* Asymmetric public-key cryptography key type
2  *
3  * See Documentation/security/asymmetric-keys.txt
4  *
5  * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
6  * Written by David Howells (dhowells@redhat.com)
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public Licence
10  * as published by the Free Software Foundation; either version
11  * 2 of the Licence, or (at your option) any later version.
12  */
13 #include <keys/asymmetric-subtype.h>
14 #include <linux/seq_file.h>
15 #include <linux/module.h>
16 #include <linux/slab.h>
17 #include "asymmetric_keys.h"
18
19 MODULE_LICENSE("GPL");
20
21 /*
22  * Match asymmetric keys on (part of) their name
23  * We have some shorthand methods for matching keys.  We allow:
24  *
25  *      "<desc>"        - request a key by description
26  *      "id:<id>"       - request a key matching the ID
27  *      "<subtype>:<id>" - request a key of a subtype
28  */
29 static int asymmetric_key_match(const struct key *key, const void *description)
30 {
31         const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
32         const char *spec = description;
33         const char *id, *kid;
34         ptrdiff_t speclen;
35         size_t idlen, kidlen;
36
37         if (!subtype || !spec || !*spec)
38                 return 0;
39
40         /* See if the full key description matches as is */
41         if (key->description && strcmp(key->description, description) == 0)
42                 return 1;
43
44         /* All tests from here on break the criterion description into a
45          * specifier, a colon and then an identifier.
46          */
47         id = strchr(spec, ':');
48         if (!id)
49                 return 0;
50
51         speclen = id - spec;
52         id++;
53
54         /* Anything after here requires a partial match on the ID string */
55         kid = asymmetric_key_id(key);
56         if (!kid)
57                 return 0;
58
59         idlen = strlen(id);
60         kidlen = strlen(kid);
61         if (idlen > kidlen)
62                 return 0;
63
64         kid += kidlen - idlen;
65         if (strcasecmp(id, kid) != 0)
66                 return 0;
67
68         if (speclen == 2 &&
69             memcmp(spec, "id", 2) == 0)
70                 return 1;
71
72         if (speclen == subtype->name_len &&
73             memcmp(spec, subtype->name, speclen) == 0)
74                 return 1;
75
76         return 0;
77 }
78
79 /*
80  * Describe the asymmetric key
81  */
82 static void asymmetric_key_describe(const struct key *key, struct seq_file *m)
83 {
84         const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
85         const char *kid = asymmetric_key_id(key);
86         size_t n;
87
88         seq_puts(m, key->description);
89
90         if (subtype) {
91                 seq_puts(m, ": ");
92                 subtype->describe(key, m);
93
94                 if (kid) {
95                         seq_putc(m, ' ');
96                         n = strlen(kid);
97                         if (n <= 8)
98                                 seq_puts(m, kid);
99                         else
100                                 seq_puts(m, kid + n - 8);
101                 }
102
103                 seq_puts(m, " [");
104                 /* put something here to indicate the key's capabilities */
105                 seq_putc(m, ']');
106         }
107 }
108
109 /*
110  * Instantiate a asymmetric_key defined key.  The key was preparsed, so we just
111  * have to transfer the data here.
112  */
113 static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
114 {
115         return -EOPNOTSUPP;
116 }
117
118 /*
119  * dispose of the data dangling from the corpse of a asymmetric key
120  */
121 static void asymmetric_key_destroy(struct key *key)
122 {
123         struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
124         if (subtype) {
125                 subtype->destroy(key->payload.data);
126                 module_put(subtype->owner);
127                 key->type_data.p[0] = NULL;
128         }
129         kfree(key->type_data.p[1]);
130         key->type_data.p[1] = NULL;
131 }
132
133 struct key_type key_type_asymmetric = {
134         .name           = "asymmetric",
135         .instantiate    = asymmetric_key_instantiate,
136         .match          = asymmetric_key_match,
137         .destroy        = asymmetric_key_destroy,
138         .describe       = asymmetric_key_describe,
139 };
140 EXPORT_SYMBOL_GPL(key_type_asymmetric);
141
142 /*
143  * Module stuff
144  */
145 static int __init asymmetric_key_init(void)
146 {
147         return register_key_type(&key_type_asymmetric);
148 }
149
150 static void __exit asymmetric_key_cleanup(void)
151 {
152         unregister_key_type(&key_type_asymmetric);
153 }
154
155 module_init(asymmetric_key_init);
156 module_exit(asymmetric_key_cleanup);