diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-14 16:39:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-14 16:39:34 -0400 |
commit | d25282d1c9b9bc4cda7f9d3c0205108e99aa7a9d (patch) | |
tree | f414482d768b015a609924293b779b4ad0b8f764 | |
parent | b6eea87fc6850d3531a64a27d2323a4498cd4e43 (diff) | |
parent | dbadc17683e6c673a69b236c0f041b931cc55c42 (diff) |
Merge branch 'modules-next' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux
Pull module signing support from Rusty Russell:
"module signing is the highlight, but it's an all-over David Howells frenzy..."
Hmm "Magrathea: Glacier signing key". Somebody has been reading too much HHGTTG.
* 'modules-next' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux: (37 commits)
X.509: Fix indefinite length element skip error handling
X.509: Convert some printk calls to pr_devel
asymmetric keys: fix printk format warning
MODSIGN: Fix 32-bit overflow in X.509 certificate validity date checking
MODSIGN: Make mrproper should remove generated files.
MODSIGN: Use utf8 strings in signer's name in autogenerated X.509 certs
MODSIGN: Use the same digest for the autogen key sig as for the module sig
MODSIGN: Sign modules during the build process
MODSIGN: Provide a script for generating a key ID from an X.509 cert
MODSIGN: Implement module signature checking
MODSIGN: Provide module signing public keys to the kernel
MODSIGN: Automatically generate module signing keys if missing
MODSIGN: Provide Kconfig options
MODSIGN: Provide gitignore and make clean rules for extra files
MODSIGN: Add FIPS policy
module: signature checking hook
X.509: Add a crypto key parser for binary (DER) X.509 certificates
MPILIB: Provide a function to read raw data into an MPI
X.509: Add an ASN.1 decoder
X.509: Add simple ASN.1 grammar compiler
...
128 files changed, 6799 insertions, 594 deletions
diff --git a/.gitignore b/.gitignore index 57af07cf7e68..0f2f40f71915 100644 --- a/.gitignore +++ b/.gitignore | |||
@@ -14,6 +14,10 @@ | |||
14 | *.o.* | 14 | *.o.* |
15 | *.a | 15 | *.a |
16 | *.s | 16 | *.s |
17 | *.ko.unsigned | ||
18 | *.ko.stripped | ||
19 | *.ko.stripped.dig | ||
20 | *.ko.stripped.sig | ||
17 | *.ko | 21 | *.ko |
18 | *.so | 22 | *.so |
19 | *.so.dbg | 23 | *.so.dbg |
@@ -84,3 +88,13 @@ GTAGS | |||
84 | *.orig | 88 | *.orig |
85 | *~ | 89 | *~ |
86 | \#*# | 90 | \#*# |
91 | |||
92 | # | ||
93 | # Leavings from module signing | ||
94 | # | ||
95 | extra_certificates | ||
96 | signing_key.priv | ||
97 | signing_key.x509 | ||
98 | signing_key.x509.keyid | ||
99 | signing_key.x509.signer | ||
100 | x509.genkey | ||
diff --git a/Documentation/crypto/asymmetric-keys.txt b/Documentation/crypto/asymmetric-keys.txt new file mode 100644 index 000000000000..b7675904a747 --- /dev/null +++ b/Documentation/crypto/asymmetric-keys.txt | |||
@@ -0,0 +1,312 @@ | |||
1 | ============================================= | ||
2 | ASYMMETRIC / PUBLIC-KEY CRYPTOGRAPHY KEY TYPE | ||
3 | ============================================= | ||
4 | |||
5 | Contents: | ||
6 | |||
7 | - Overview. | ||
8 | - Key identification. | ||
9 | - Accessing asymmetric keys. | ||
10 | - Signature verification. | ||
11 | - Asymmetric key subtypes. | ||
12 | - Instantiation data parsers. | ||
13 | |||
14 | |||
15 | ======== | ||
16 | OVERVIEW | ||
17 | ======== | ||
18 | |||
19 | The "asymmetric" key type is designed to be a container for the keys used in | ||
20 | public-key cryptography, without imposing any particular restrictions on the | ||
21 | form or mechanism of the cryptography or form of the key. | ||
22 | |||
23 | The asymmetric key is given a subtype that defines what sort of data is | ||
24 | associated with the key and provides operations to describe and destroy it. | ||
25 | However, no requirement is made that the key data actually be stored in the | ||
26 | key. | ||
27 | |||
28 | A completely in-kernel key retention and operation subtype can be defined, but | ||
29 | it would also be possible to provide access to cryptographic hardware (such as | ||
30 | a TPM) that might be used to both retain the relevant key and perform | ||
31 | operations using that key. In such a case, the asymmetric key would then | ||
32 | merely be an interface to the TPM driver. | ||
33 | |||
34 | Also provided is the concept of a data parser. Data parsers are responsible | ||
35 | for extracting information from the blobs of data passed to the instantiation | ||
36 | function. The first data parser that recognises the blob gets to set the | ||
37 | subtype of the key and define the operations that can be done on that key. | ||
38 | |||
39 | A data parser may interpret the data blob as containing the bits representing a | ||
40 | key, or it may interpret it as a reference to a key held somewhere else in the | ||
41 | system (for example, a TPM). | ||
42 | |||
43 | |||
44 | ================== | ||
45 | KEY IDENTIFICATION | ||
46 | ================== | ||
47 | |||
48 | If a key is added with an empty name, the instantiation data parsers are given | ||
49 | the opportunity to pre-parse a key and to determine the description the key | ||
50 | should be given from the content of the key. | ||
51 | |||
52 | This can then be used to refer to the key, either by complete match or by | ||
53 | partial match. The key type may also use other criteria to refer to a key. | ||
54 | |||
55 | The asymmetric key type's match function can then perform a wider range of | ||
56 | comparisons than just the straightforward comparison of the description with | ||
57 | the criterion string: | ||
58 | |||
59 | (1) If the criterion string is of the form "id:<hexdigits>" then the match | ||
60 | function will examine a key's fingerprint to see if the hex digits given | ||
61 | after the "id:" match the tail. For instance: | ||
62 | |||
63 | keyctl search @s asymmetric id:5acc2142 | ||
64 | |||
65 | will match a key with fingerprint: | ||
66 | |||
67 | 1A00 2040 7601 7889 DE11 882C 3823 04AD 5ACC 2142 | ||
68 | |||
69 | (2) If the criterion string is of the form "<subtype>:<hexdigits>" then the | ||
70 | match will match the ID as in (1), but with the added restriction that | ||
71 | only keys of the specified subtype (e.g. tpm) will be matched. For | ||
72 | instance: | ||
73 | |||
74 | keyctl search @s asymmetric tpm:5acc2142 | ||
75 | |||
76 | Looking in /proc/keys, the last 8 hex digits of the key fingerprint are | ||
77 | displayed, along with the subtype: | ||
78 | |||
79 | 1a39e171 I----- 1 perm 3f010000 0 0 asymmetri modsign.0: DSA 5acc2142 [] | ||
80 | |||
81 | |||
82 | ========================= | ||
83 | ACCESSING ASYMMETRIC KEYS | ||
84 | ========================= | ||
85 | |||
86 | For general access to asymmetric keys from within the kernel, the following | ||
87 | inclusion is required: | ||
88 | |||
89 | #include <crypto/public_key.h> | ||
90 | |||
91 | This gives access to functions for dealing with asymmetric / public keys. | ||
92 | Three enums are defined there for representing public-key cryptography | ||
93 | algorithms: | ||
94 | |||
95 | enum pkey_algo | ||
96 | |||
97 | digest algorithms used by those: | ||
98 | |||
99 | enum pkey_hash_algo | ||
100 | |||
101 | and key identifier representations: | ||
102 | |||
103 | enum pkey_id_type | ||
104 | |||
105 | Note that the key type representation types are required because key | ||
106 | identifiers from different standards aren't necessarily compatible. For | ||
107 | instance, PGP generates key identifiers by hashing the key data plus some | ||
108 | PGP-specific metadata, whereas X.509 has arbitrary certificate identifiers. | ||
109 | |||
110 | The operations defined upon a key are: | ||
111 | |||
112 | (1) Signature verification. | ||
113 | |||
114 | Other operations are possible (such as encryption) with the same key data | ||
115 | required for verification, but not currently supported, and others | ||
116 | (eg. decryption and signature generation) require extra key data. | ||
117 | |||
118 | |||
119 | SIGNATURE VERIFICATION | ||
120 | ---------------------- | ||
121 | |||
122 | An operation is provided to perform cryptographic signature verification, using | ||
123 | an asymmetric key to provide or to provide access to the public key. | ||
124 | |||
125 | int verify_signature(const struct key *key, | ||
126 | const struct public_key_signature *sig); | ||
127 | |||
128 | The caller must have already obtained the key from some source and can then use | ||
129 | it to check the signature. The caller must have parsed the signature and | ||
130 | transferred the relevant bits to the structure pointed to by sig. | ||
131 | |||
132 | struct public_key_signature { | ||
133 | u8 *digest; | ||
134 | u8 digest_size; | ||
135 | enum pkey_hash_algo pkey_hash_algo : 8; | ||
136 | u8 nr_mpi; | ||
137 | union { | ||
138 | MPI mpi[2]; | ||
139 | ... | ||
140 | }; | ||
141 | }; | ||
142 | |||
143 | The algorithm used must be noted in sig->pkey_hash_algo, and all the MPIs that | ||
144 | make up the actual signature must be stored in sig->mpi[] and the count of MPIs | ||
145 | placed in sig->nr_mpi. | ||
146 | |||
147 | In addition, the data must have been digested by the caller and the resulting | ||
148 | hash must be pointed to by sig->digest and the size of the hash be placed in | ||
149 | sig->digest_size. | ||
150 | |||
151 | The function will return 0 upon success or -EKEYREJECTED if the signature | ||
152 | doesn't match. | ||
153 | |||
154 | The function may also return -ENOTSUPP if an unsupported public-key algorithm | ||
155 | or public-key/hash algorithm combination is specified or the key doesn't | ||
156 | support the operation; -EBADMSG or -ERANGE if some of the parameters have weird | ||
157 | data; or -ENOMEM if an allocation can't be performed. -EINVAL can be returned | ||
158 | if the key argument is the wrong type or is incompletely set up. | ||
159 | |||
160 | |||
161 | ======================= | ||
162 | ASYMMETRIC KEY SUBTYPES | ||
163 | ======================= | ||
164 | |||
165 | Asymmetric keys have a subtype that defines the set of operations that can be | ||
166 | performed on that key and that determines what data is attached as the key | ||
167 | payload. The payload format is entirely at the whim of the subtype. | ||
168 | |||
169 | The subtype is selected by the key data parser and the parser must initialise | ||
170 | the data required for it. The asymmetric key retains a reference on the | ||
171 | subtype module. | ||
172 | |||
173 | The subtype definition structure can be found in: | ||
174 | |||
175 | #include <keys/asymmetric-subtype.h> | ||
176 | |||
177 | and looks like the following: | ||
178 | |||
179 | struct asymmetric_key_subtype { | ||
180 | struct module *owner; | ||
181 | const char *name; | ||
182 | |||
183 | void (*describe)(const struct key *key, struct seq_file *m); | ||
184 | void (*destroy)(void *payload); | ||
185 | int (*verify_signature)(const struct key *key, | ||
186 | const struct public_key_signature *sig); | ||
187 | }; | ||
188 | |||
189 | Asymmetric keys point to this with their type_data[0] member. | ||
190 | |||
191 | The owner and name fields should be set to the owning module and the name of | ||
192 | the subtype. Currently, the name is only used for print statements. | ||
193 | |||
194 | There are a number of operations defined by the subtype: | ||
195 | |||
196 | (1) describe(). | ||
197 | |||
198 | Mandatory. This allows the subtype to display something in /proc/keys | ||
199 | against the key. For instance the name of the public key algorithm type | ||
200 | could be displayed. The key type will display the tail of the key | ||
201 | identity string after this. | ||
202 | |||
203 | (2) destroy(). | ||
204 | |||
205 | Mandatory. This should free the memory associated with the key. The | ||
206 | asymmetric key will look after freeing the fingerprint and releasing the | ||
207 | reference on the subtype module. | ||
208 | |||
209 | (3) verify_signature(). | ||
210 | |||
211 | Optional. These are the entry points for the key usage operations. | ||
212 | Currently there is only the one defined. If not set, the caller will be | ||
213 | given -ENOTSUPP. The subtype may do anything it likes to implement an | ||
214 | operation, including offloading to hardware. | ||
215 | |||
216 | |||
217 | ========================== | ||
218 | INSTANTIATION DATA PARSERS | ||
219 | ========================== | ||
220 | |||
221 | The asymmetric key type doesn't generally want to store or to deal with a raw | ||
222 | blob of data that holds the key data. It would have to parse it and error | ||
223 | check it each time it wanted to use it. Further, the contents of the blob may | ||
224 | have various checks that can be performed on it (eg. self-signatures, validity | ||
225 | dates) and may contain useful data about the key (identifiers, capabilities). | ||
226 | |||
227 | Also, the blob may represent a pointer to some hardware containing the key | ||
228 | rather than the key itself. | ||
229 | |||
230 | Examples of blob formats for which parsers could be implemented include: | ||
231 | |||
232 | - OpenPGP packet stream [RFC 4880]. | ||
233 | - X.509 ASN.1 stream. | ||
234 | - Pointer to TPM key. | ||
235 | - Pointer to UEFI key. | ||
236 | |||
237 | During key instantiation each parser in the list is tried until one doesn't | ||
238 | return -EBADMSG. | ||
239 | |||
240 | The parser definition structure can be found in: | ||
241 | |||
242 | #include <keys/asymmetric-parser.h> | ||
243 | |||
244 | and looks like the following: | ||
245 | |||
246 | struct asymmetric_key_parser { | ||
247 | struct module *owner; | ||
248 | const char *name; | ||
249 | |||
250 | int (*parse)(struct key_preparsed_payload *prep); | ||
251 | }; | ||
252 | |||
253 | The owner and name fields should be set to the owning module and the name of | ||
254 | the parser. | ||
255 | |||
256 | There is currently only a single operation defined by the parser, and it is | ||
257 | mandatory: | ||
258 | |||
259 | (1) parse(). | ||
260 | |||
261 | This is called to preparse the key from the key creation and update paths. | ||
262 | In particular, it is called during the key creation _before_ a key is | ||
263 | allocated, and as such, is permitted to provide the key's description in | ||
264 | the case that the caller declines to do so. | ||
265 | |||
266 | The caller passes a pointer to the following struct with all of the fields | ||
267 | cleared, except for data, datalen and quotalen [see | ||
268 | Documentation/security/keys.txt]. | ||
269 | |||
270 | struct key_preparsed_payload { | ||
271 | char *description; | ||
272 | void *type_data[2]; | ||
273 | void *payload; | ||
274 | const void *data; | ||
275 | size_t datalen; | ||
276 | size_t quotalen; | ||
277 | }; | ||
278 | |||
279 | The instantiation data is in a blob pointed to by data and is datalen in | ||
280 | size. The parse() function is not permitted to change these two values at | ||
281 | all, and shouldn't change any of the other values _unless_ they are | ||
282 | recognise the blob format and will not return -EBADMSG to indicate it is | ||
283 | not theirs. | ||
284 | |||
285 | If the parser is happy with the blob, it should propose a description for | ||
286 | the key and attach it to ->description, ->type_data[0] should be set to | ||
287 | point to the subtype to be used, ->payload should be set to point to the | ||
288 | initialised data for that subtype, ->type_data[1] should point to a hex | ||
289 | fingerprint and quotalen should be updated to indicate how much quota this | ||
290 | key should account for. | ||
291 | |||
292 | When clearing up, the data attached to ->type_data[1] and ->description | ||
293 | will be kfree()'d and the data attached to ->payload will be passed to the | ||
294 | subtype's ->destroy() method to be disposed of. A module reference for | ||
295 | the subtype pointed to by ->type_data[0] will be put. | ||
296 | |||
297 | |||
298 | If the data format is not recognised, -EBADMSG should be returned. If it | ||
299 | is recognised, but the key cannot for some reason be set up, some other | ||
300 | negative error code should be returned. On success, 0 should be returned. | ||
301 | |||
302 | The key's fingerprint string may be partially matched upon. For a | ||
303 | public-key algorithm such as RSA and DSA this will likely be a printable | ||
304 | hex version of the key's fingerprint. | ||
305 | |||
306 | Functions are provided to register and unregister parsers: | ||
307 | |||
308 | int register_asymmetric_key_parser(struct asymmetric_key_parser *parser); | ||
309 | void unregister_asymmetric_key_parser(struct asymmetric_key_parser *subtype); | ||
310 | |||
311 | Parsers may not have the same name. The names are otherwise only used for | ||
312 | displaying in debugging messages. | ||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index e2ed3360b708..9776f068306b 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1593,6 +1593,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
1593 | log everything. Information is printed at KERN_DEBUG | 1593 | log everything. Information is printed at KERN_DEBUG |
1594 | so loglevel=8 may also need to be specified. | 1594 | so loglevel=8 may also need to be specified. |
1595 | 1595 | ||
1596 | module.sig_enforce | ||
1597 | [KNL] When CONFIG_MODULE_SIG is set, this means that | ||
1598 | modules without (valid) signatures will fail to load. | ||
1599 | Note that if CONFIG_MODULE_SIG_ENFORCE is set, that | ||
1600 | is always true, so this option does nothing. | ||
1601 | |||
1596 | mousedev.tap_time= | 1602 | mousedev.tap_time= |
1597 | [MOUSE] Maximum time between finger touching and | 1603 | [MOUSE] Maximum time between finger touching and |
1598 | leaving touchpad surface for touch to be considered | 1604 | leaving touchpad surface for touch to be considered |
diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt index aa0dbd74b71b..7d9ca92022d8 100644 --- a/Documentation/security/keys.txt +++ b/Documentation/security/keys.txt | |||
@@ -412,6 +412,10 @@ The main syscalls are: | |||
412 | to the keyring. In this case, an error will be generated if the process | 412 | to the keyring. In this case, an error will be generated if the process |
413 | does not have permission to write to the keyring. | 413 | does not have permission to write to the keyring. |
414 | 414 | ||
415 | If the key type supports it, if the description is NULL or an empty | ||
416 | string, the key type will try and generate a description from the content | ||
417 | of the payload. | ||
418 | |||
415 | The payload is optional, and the pointer can be NULL if not required by | 419 | The payload is optional, and the pointer can be NULL if not required by |
416 | the type. The payload is plen in size, and plen can be zero for an empty | 420 | the type. The payload is plen in size, and plen can be zero for an empty |
417 | payload. | 421 | payload. |
@@ -1114,12 +1118,53 @@ The structure has a number of fields, some of which are mandatory: | |||
1114 | it should return 0. | 1118 | it should return 0. |
1115 | 1119 | ||
1116 | 1120 | ||
1117 | (*) int (*instantiate)(struct key *key, const void *data, size_t datalen); | 1121 | (*) int (*preparse)(struct key_preparsed_payload *prep); |
1122 | |||
1123 | This optional method permits the key type to attempt to parse payload | ||
1124 | before a key is created (add key) or the key semaphore is taken (update or | ||
1125 | instantiate key). The structure pointed to by prep looks like: | ||
1126 | |||
1127 | struct key_preparsed_payload { | ||
1128 | char *description; | ||
1129 | void *type_data[2]; | ||
1130 | void *payload; | ||
1131 | const void *data; | ||
1132 | size_t datalen; | ||
1133 | size_t quotalen; | ||
1134 | }; | ||
1135 | |||
1136 | Before calling the method, the caller will fill in data and datalen with | ||
1137 | the payload blob parameters; quotalen will be filled in with the default | ||
1138 | quota size from the key type and the rest will be cleared. | ||
1139 | |||
1140 | If a description can be proposed from the payload contents, that should be | ||
1141 | attached as a string to the description field. This will be used for the | ||
1142 | key description if the caller of add_key() passes NULL or "". | ||
1143 | |||
1144 | The method can attach anything it likes to type_data[] and payload. These | ||
1145 | are merely passed along to the instantiate() or update() operations. | ||
1146 | |||
1147 | The method should return 0 if success ful or a negative error code | ||
1148 | otherwise. | ||
1149 | |||
1150 | |||
1151 | (*) void (*free_preparse)(struct key_preparsed_payload *prep); | ||
1152 | |||
1153 | This method is only required if the preparse() method is provided, | ||
1154 | otherwise it is unused. It cleans up anything attached to the | ||
1155 | description, type_data and payload fields of the key_preparsed_payload | ||
1156 | struct as filled in by the preparse() method. | ||
1157 | |||
1158 | |||
1159 | (*) int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); | ||
1118 | 1160 | ||
1119 | This method is called to attach a payload to a key during construction. | 1161 | This method is called to attach a payload to a key during construction. |
1120 | The payload attached need not bear any relation to the data passed to this | 1162 | The payload attached need not bear any relation to the data passed to this |
1121 | function. | 1163 | function. |
1122 | 1164 | ||
1165 | The prep->data and prep->datalen fields will define the original payload | ||
1166 | blob. If preparse() was supplied then other fields may be filled in also. | ||
1167 | |||
1123 | If the amount of data attached to the key differs from the size in | 1168 | If the amount of data attached to the key differs from the size in |
1124 | keytype->def_datalen, then key_payload_reserve() should be called. | 1169 | keytype->def_datalen, then key_payload_reserve() should be called. |
1125 | 1170 | ||
@@ -1135,6 +1180,9 @@ The structure has a number of fields, some of which are mandatory: | |||
1135 | If this type of key can be updated, then this method should be provided. | 1180 | If this type of key can be updated, then this method should be provided. |
1136 | It is called to update a key's payload from the blob of data provided. | 1181 | It is called to update a key's payload from the blob of data provided. |
1137 | 1182 | ||
1183 | The prep->data and prep->datalen fields will define the original payload | ||
1184 | blob. If preparse() was supplied then other fields may be filled in also. | ||
1185 | |||
1138 | key_payload_reserve() should be called if the data length might change | 1186 | key_payload_reserve() should be called if the data length might change |
1139 | before any changes are actually made. Note that if this succeeds, the type | 1187 | before any changes are actually made. Note that if this succeeds, the type |
1140 | is committed to changing the key because it's already been altered, so all | 1188 | is committed to changing the key because it's already been altered, so all |
@@ -997,7 +997,10 @@ CLEAN_DIRS += $(MODVERDIR) | |||
997 | MRPROPER_DIRS += include/config usr/include include/generated \ | 997 | MRPROPER_DIRS += include/config usr/include include/generated \ |
998 | arch/*/include/generated | 998 | arch/*/include/generated |
999 | MRPROPER_FILES += .config .config.old .version .old_version $(version_h) \ | 999 | MRPROPER_FILES += .config .config.old .version .old_version $(version_h) \ |
1000 | Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS | 1000 | Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \ |
1001 | signing_key.priv signing_key.x509 x509.genkey \ | ||
1002 | extra_certificates signing_key.x509.keyid \ | ||
1003 | signing_key.x509.signer | ||
1001 | 1004 | ||
1002 | # clean - Delete most, but leave enough to build external modules | 1005 | # clean - Delete most, but leave enough to build external modules |
1003 | # | 1006 | # |
@@ -1241,6 +1244,7 @@ clean: $(clean-dirs) | |||
1241 | $(call cmd,rmfiles) | 1244 | $(call cmd,rmfiles) |
1242 | @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ | 1245 | @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ |
1243 | \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ | 1246 | \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ |
1247 | -o -name '*.ko.*' \ | ||
1244 | -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ | 1248 | -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ |
1245 | -o -name '*.symtypes' -o -name 'modules.order' \ | 1249 | -o -name '*.symtypes' -o -name 'modules.order' \ |
1246 | -o -name modules.builtin -o -name '.tmp_*.o.*' \ | 1250 | -o -name modules.builtin -o -name '.tmp_*.o.*' \ |
diff --git a/arch/Kconfig b/arch/Kconfig index a79a1ad8bb96..366ec06a5185 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
@@ -322,4 +322,23 @@ config HAVE_IRQ_TIME_ACCOUNTING | |||
322 | config HAVE_ARCH_TRANSPARENT_HUGEPAGE | 322 | config HAVE_ARCH_TRANSPARENT_HUGEPAGE |
323 | bool | 323 | bool |
324 | 324 | ||
325 | config HAVE_MOD_ARCH_SPECIFIC | ||
326 | bool | ||
327 | help | ||
328 | The arch uses struct mod_arch_specific to store data. Many arches | ||
329 | just need a simple module loader without arch specific data - those | ||
330 | should not enable this. | ||
331 | |||
332 | config MODULES_USE_ELF_RELA | ||
333 | bool | ||
334 | help | ||
335 | Modules only use ELF RELA relocations. Modules with ELF REL | ||
336 | relocations will give an error. | ||
337 | |||
338 | config MODULES_USE_ELF_REL | ||
339 | bool | ||
340 | help | ||
341 | Modules only use ELF REL relocations. Modules with ELF RELA | ||
342 | relocations will give an error. | ||
343 | |||
325 | source "kernel/gcov/Kconfig" | 344 | source "kernel/gcov/Kconfig" |
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 7a08cfb80ee8..5dd7f5db24d4 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig | |||
@@ -22,6 +22,8 @@ config ALPHA | |||
22 | select GENERIC_STRNLEN_USER | 22 | select GENERIC_STRNLEN_USER |
23 | select GENERIC_KERNEL_THREAD | 23 | select GENERIC_KERNEL_THREAD |
24 | select GENERIC_KERNEL_EXECVE | 24 | select GENERIC_KERNEL_EXECVE |
25 | select HAVE_MOD_ARCH_SPECIFIC | ||
26 | select MODULES_USE_ELF_RELA | ||
25 | help | 27 | help |
26 | The Alpha is a 64-bit general-purpose processor designed and | 28 | The Alpha is a 64-bit general-purpose processor designed and |
27 | marketed by the Digital Equipment Corporation of blessed memory, | 29 | marketed by the Digital Equipment Corporation of blessed memory, |
diff --git a/arch/alpha/include/asm/module.h b/arch/alpha/include/asm/module.h index 7b63743c534a..9cd13b55155f 100644 --- a/arch/alpha/include/asm/module.h +++ b/arch/alpha/include/asm/module.h | |||
@@ -1,19 +1,13 @@ | |||
1 | #ifndef _ALPHA_MODULE_H | 1 | #ifndef _ALPHA_MODULE_H |
2 | #define _ALPHA_MODULE_H | 2 | #define _ALPHA_MODULE_H |
3 | 3 | ||
4 | #include <asm-generic/module.h> | ||
5 | |||
4 | struct mod_arch_specific | 6 | struct mod_arch_specific |
5 | { | 7 | { |
6 | unsigned int gotsecindex; | 8 | unsigned int gotsecindex; |
7 | }; | 9 | }; |
8 | 10 | ||
9 | #define Elf_Sym Elf64_Sym | ||
10 | #define Elf_Shdr Elf64_Shdr | ||
11 | #define Elf_Ehdr Elf64_Ehdr | ||
12 | #define Elf_Phdr Elf64_Phdr | ||
13 | #define Elf_Dyn Elf64_Dyn | ||
14 | #define Elf_Rel Elf64_Rel | ||
15 | #define Elf_Rela Elf64_Rela | ||
16 | |||
17 | #define ARCH_SHF_SMALL SHF_ALPHA_GPREL | 11 | #define ARCH_SHF_SMALL SHF_ALPHA_GPREL |
18 | 12 | ||
19 | #ifdef MODULE | 13 | #ifdef MODULE |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 261fdd085bb9..73067efd4845 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -53,6 +53,8 @@ config ARM | |||
53 | select PERF_USE_VMALLOC | 53 | select PERF_USE_VMALLOC |
54 | select RTC_LIB | 54 | select RTC_LIB |
55 | select SYS_SUPPORTS_APM_EMULATION | 55 | select SYS_SUPPORTS_APM_EMULATION |
56 | select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND | ||
57 | select MODULES_USE_ELF_REL | ||
56 | help | 58 | help |
57 | The ARM series is a line of low-power-consumption RISC chip designs | 59 | The ARM series is a line of low-power-consumption RISC chip designs |
58 | licensed by ARM Ltd and targeted at embedded applications and | 60 | licensed by ARM Ltd and targeted at embedded applications and |
diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h index 6c6809f982f1..0d3a28dbc8e5 100644 --- a/arch/arm/include/asm/module.h +++ b/arch/arm/include/asm/module.h | |||
@@ -1,9 +1,7 @@ | |||
1 | #ifndef _ASM_ARM_MODULE_H | 1 | #ifndef _ASM_ARM_MODULE_H |
2 | #define _ASM_ARM_MODULE_H | 2 | #define _ASM_ARM_MODULE_H |
3 | 3 | ||
4 | #define Elf_Shdr Elf32_Shdr | 4 | #include <asm-generic/module.h> |
5 | #define Elf_Sym Elf32_Sym | ||
6 | #define Elf_Ehdr Elf32_Ehdr | ||
7 | 5 | ||
8 | struct unwind_table; | 6 | struct unwind_table; |
9 | 7 | ||
@@ -16,13 +14,11 @@ enum { | |||
16 | ARM_SEC_DEVEXIT, | 14 | ARM_SEC_DEVEXIT, |
17 | ARM_SEC_MAX, | 15 | ARM_SEC_MAX, |
18 | }; | 16 | }; |
19 | #endif | ||
20 | 17 | ||
21 | struct mod_arch_specific { | 18 | struct mod_arch_specific { |
22 | #ifdef CONFIG_ARM_UNWIND | ||
23 | struct unwind_table *unwind[ARM_SEC_MAX]; | 19 | struct unwind_table *unwind[ARM_SEC_MAX]; |
24 | #endif | ||
25 | }; | 20 | }; |
21 | #endif | ||
26 | 22 | ||
27 | /* | 23 | /* |
28 | * Add the ARM architecture version to the version magic string | 24 | * Add the ARM architecture version to the version magic string |
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index 5ade51c8a87f..06e73bf665e9 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig | |||
@@ -15,6 +15,8 @@ config AVR32 | |||
15 | select ARCH_WANT_IPC_PARSE_VERSION | 15 | select ARCH_WANT_IPC_PARSE_VERSION |
16 | select ARCH_HAVE_NMI_SAFE_CMPXCHG | 16 | select ARCH_HAVE_NMI_SAFE_CMPXCHG |
17 | select GENERIC_CLOCKEVENTS | 17 | select GENERIC_CLOCKEVENTS |
18 | select HAVE_MOD_ARCH_SPECIFIC | ||
19 | select MODULES_USE_ELF_RELA | ||
18 | help | 20 | help |
19 | AVR32 is a high-performance 32-bit RISC microprocessor core, | 21 | AVR32 is a high-performance 32-bit RISC microprocessor core, |
20 | designed for cost-sensitive embedded applications, with particular | 22 | designed for cost-sensitive embedded applications, with particular |
diff --git a/arch/avr32/include/asm/module.h b/arch/avr32/include/asm/module.h index 451444538a1b..3f083d385a64 100644 --- a/arch/avr32/include/asm/module.h +++ b/arch/avr32/include/asm/module.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef __ASM_AVR32_MODULE_H | 1 | #ifndef __ASM_AVR32_MODULE_H |
2 | #define __ASM_AVR32_MODULE_H | 2 | #define __ASM_AVR32_MODULE_H |
3 | 3 | ||
4 | #include <asm-generic/module.h> | ||
5 | |||
4 | struct mod_arch_syminfo { | 6 | struct mod_arch_syminfo { |
5 | unsigned long got_offset; | 7 | unsigned long got_offset; |
6 | int got_initialized; | 8 | int got_initialized; |
@@ -17,10 +19,6 @@ struct mod_arch_specific { | |||
17 | struct mod_arch_syminfo *syminfo; | 19 | struct mod_arch_syminfo *syminfo; |
18 | }; | 20 | }; |
19 | 21 | ||
20 | #define Elf_Shdr Elf32_Shdr | ||
21 | #define Elf_Sym Elf32_Sym | ||
22 | #define Elf_Ehdr Elf32_Ehdr | ||
23 | |||
24 | #define MODULE_PROC_FAMILY "AVR32v1" | 22 | #define MODULE_PROC_FAMILY "AVR32v1" |
25 | 23 | ||
26 | #define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY | 24 | #define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY |
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index ccd9193932b2..b6f3ad5441c5 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig | |||
@@ -43,6 +43,8 @@ config BLACKFIN | |||
43 | select HAVE_NMI_WATCHDOG if NMI_WATCHDOG | 43 | select HAVE_NMI_WATCHDOG if NMI_WATCHDOG |
44 | select GENERIC_SMP_IDLE_THREAD | 44 | select GENERIC_SMP_IDLE_THREAD |
45 | select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS | 45 | select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS |
46 | select HAVE_MOD_ARCH_SPECIFIC | ||
47 | select MODULES_USE_ELF_RELA | ||
46 | 48 | ||
47 | config GENERIC_CSUM | 49 | config GENERIC_CSUM |
48 | def_bool y | 50 | def_bool y |
diff --git a/arch/blackfin/include/asm/module.h b/arch/blackfin/include/asm/module.h index ed5689b82c9f..231a149b3f77 100644 --- a/arch/blackfin/include/asm/module.h +++ b/arch/blackfin/include/asm/module.h | |||
@@ -7,9 +7,7 @@ | |||
7 | #ifndef _ASM_BFIN_MODULE_H | 7 | #ifndef _ASM_BFIN_MODULE_H |
8 | #define _ASM_BFIN_MODULE_H | 8 | #define _ASM_BFIN_MODULE_H |
9 | 9 | ||
10 | #define Elf_Shdr Elf32_Shdr | 10 | #include <asm-generic/module.h> |
11 | #define Elf_Sym Elf32_Sym | ||
12 | #define Elf_Ehdr Elf32_Ehdr | ||
13 | 11 | ||
14 | struct mod_arch_specific { | 12 | struct mod_arch_specific { |
15 | Elf_Shdr *text_l1; | 13 | Elf_Shdr *text_l1; |
diff --git a/arch/c6x/Kconfig b/arch/c6x/Kconfig index 45268b50c0c8..aee1b569ee6e 100644 --- a/arch/c6x/Kconfig +++ b/arch/c6x/Kconfig | |||
@@ -18,6 +18,7 @@ config C6X | |||
18 | select OF_EARLY_FLATTREE | 18 | select OF_EARLY_FLATTREE |
19 | select GENERIC_CLOCKEVENTS | 19 | select GENERIC_CLOCKEVENTS |
20 | select GENERIC_KERNEL_THREAD | 20 | select GENERIC_KERNEL_THREAD |
21 | select MODULES_USE_ELF_RELA | ||
21 | 22 | ||
22 | config MMU | 23 | config MMU |
23 | def_bool n | 24 | def_bool n |
diff --git a/arch/c6x/include/asm/module.h b/arch/c6x/include/asm/module.h index a453f9744f42..5c7269c7ef73 100644 --- a/arch/c6x/include/asm/module.h +++ b/arch/c6x/include/asm/module.h | |||
@@ -13,17 +13,7 @@ | |||
13 | #ifndef _ASM_C6X_MODULE_H | 13 | #ifndef _ASM_C6X_MODULE_H |
14 | #define _ASM_C6X_MODULE_H | 14 | #define _ASM_C6X_MODULE_H |
15 | 15 | ||
16 | #define Elf_Shdr Elf32_Shdr | 16 | #include <asm-generic/module.h> |
17 | #define Elf_Sym Elf32_Sym | ||
18 | #define Elf_Ehdr Elf32_Ehdr | ||
19 | #define Elf_Addr Elf32_Addr | ||
20 | #define Elf_Word Elf32_Word | ||
21 | |||
22 | /* | ||
23 | * This file contains the C6x architecture specific module code. | ||
24 | */ | ||
25 | struct mod_arch_specific { | ||
26 | }; | ||
27 | 17 | ||
28 | struct loaded_sections { | 18 | struct loaded_sections { |
29 | unsigned int new_vaddr; | 19 | unsigned int new_vaddr; |
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index a118163b04ee..a67244473a39 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig | |||
@@ -48,6 +48,7 @@ config CRIS | |||
48 | select GENERIC_IOMAP | 48 | select GENERIC_IOMAP |
49 | select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32 | 49 | select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32 |
50 | select GENERIC_CMOS_UPDATE | 50 | select GENERIC_CMOS_UPDATE |
51 | select MODULES_USE_ELF_RELA | ||
51 | 52 | ||
52 | config HZ | 53 | config HZ |
53 | int | 54 | int |
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild index ff1bf7fcae8e..6d43a951b5ec 100644 --- a/arch/cris/include/asm/Kbuild +++ b/arch/cris/include/asm/Kbuild | |||
@@ -10,3 +10,4 @@ header-y += sync_serial.h | |||
10 | 10 | ||
11 | generic-y += clkdev.h | 11 | generic-y += clkdev.h |
12 | generic-y += exec.h | 12 | generic-y += exec.h |
13 | generic-y += module.h | ||
diff --git a/arch/cris/include/asm/module.h b/arch/cris/include/asm/module.h deleted file mode 100644 index 7ee72311bd78..000000000000 --- a/arch/cris/include/asm/module.h +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | #ifndef _ASM_CRIS_MODULE_H | ||
2 | #define _ASM_CRIS_MODULE_H | ||
3 | /* cris is simple */ | ||
4 | struct mod_arch_specific { }; | ||
5 | |||
6 | #define Elf_Shdr Elf32_Shdr | ||
7 | #define Elf_Sym Elf32_Sym | ||
8 | #define Elf_Ehdr Elf32_Ehdr | ||
9 | #endif /* _ASM_CRIS_MODULE_H */ | ||
diff --git a/arch/frv/include/asm/module.h b/arch/frv/include/asm/module.h index 3d5c6360289a..a8848f09a217 100644 --- a/arch/frv/include/asm/module.h +++ b/arch/frv/include/asm/module.h | |||
@@ -11,13 +11,7 @@ | |||
11 | #ifndef _ASM_MODULE_H | 11 | #ifndef _ASM_MODULE_H |
12 | #define _ASM_MODULE_H | 12 | #define _ASM_MODULE_H |
13 | 13 | ||
14 | struct mod_arch_specific | 14 | #include <asm-generic/module.h> |
15 | { | ||
16 | }; | ||
17 | |||
18 | #define Elf_Shdr Elf32_Shdr | ||
19 | #define Elf_Sym Elf32_Sym | ||
20 | #define Elf_Ehdr Elf32_Ehdr | ||
21 | 15 | ||
22 | /* | 16 | /* |
23 | * Include the architecture version. | 17 | * Include the architecture version. |
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig index 90462eb23d02..98fabd10e95f 100644 --- a/arch/h8300/Kconfig +++ b/arch/h8300/Kconfig | |||
@@ -7,6 +7,7 @@ config H8300 | |||
7 | select ARCH_WANT_IPC_PARSE_VERSION | 7 | select ARCH_WANT_IPC_PARSE_VERSION |
8 | select GENERIC_IRQ_SHOW | 8 | select GENERIC_IRQ_SHOW |
9 | select GENERIC_CPU_DEVICES | 9 | select GENERIC_CPU_DEVICES |
10 | select MODULES_USE_ELF_RELA | ||
10 | 11 | ||
11 | config SYMBOL_PREFIX | 12 | config SYMBOL_PREFIX |
12 | string | 13 | string |
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild index fccd81eddff1..50bbf387b2f8 100644 --- a/arch/h8300/include/asm/Kbuild +++ b/arch/h8300/include/asm/Kbuild | |||
@@ -2,3 +2,4 @@ include include/asm-generic/Kbuild.asm | |||
2 | 2 | ||
3 | generic-y += clkdev.h | 3 | generic-y += clkdev.h |
4 | generic-y += exec.h | 4 | generic-y += exec.h |
5 | generic-y += module.h | ||
diff --git a/arch/h8300/include/asm/module.h b/arch/h8300/include/asm/module.h deleted file mode 100644 index 8e46724b7c09..000000000000 --- a/arch/h8300/include/asm/module.h +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | #ifndef _ASM_H8300_MODULE_H | ||
2 | #define _ASM_H8300_MODULE_H | ||
3 | /* | ||
4 | * This file contains the H8/300 architecture specific module code. | ||
5 | */ | ||
6 | struct mod_arch_specific { }; | ||
7 | #define Elf_Shdr Elf32_Shdr | ||
8 | #define Elf_Sym Elf32_Sym | ||
9 | #define Elf_Ehdr Elf32_Ehdr | ||
10 | |||
11 | #endif /* _ASM_H8/300_MODULE_H */ | ||
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig index b2fdfb700f50..0744f7d7b1fd 100644 --- a/arch/hexagon/Kconfig +++ b/arch/hexagon/Kconfig | |||
@@ -30,6 +30,7 @@ config HEXAGON | |||
30 | select KTIME_SCALAR | 30 | select KTIME_SCALAR |
31 | select GENERIC_CLOCKEVENTS | 31 | select GENERIC_CLOCKEVENTS |
32 | select GENERIC_CLOCKEVENTS_BROADCAST | 32 | select GENERIC_CLOCKEVENTS_BROADCAST |
33 | select MODULES_USE_ELF_RELA | ||
33 | ---help--- | 34 | ---help--- |
34 | Qualcomm Hexagon is a processor architecture designed for high | 35 | Qualcomm Hexagon is a processor architecture designed for high |
35 | performance and low power across a wide variety of applications. | 36 | performance and low power across a wide variety of applications. |
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 4c10e607c908..3279646120e3 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
@@ -40,6 +40,8 @@ config IA64 | |||
40 | select ARCH_THREAD_INFO_ALLOCATOR | 40 | select ARCH_THREAD_INFO_ALLOCATOR |
41 | select ARCH_CLOCKSOURCE_DATA | 41 | select ARCH_CLOCKSOURCE_DATA |
42 | select GENERIC_TIME_VSYSCALL_OLD | 42 | select GENERIC_TIME_VSYSCALL_OLD |
43 | select HAVE_MOD_ARCH_SPECIFIC | ||
44 | select MODULES_USE_ELF_RELA | ||
43 | default y | 45 | default y |
44 | help | 46 | help |
45 | The Itanium Processor Family is Intel's 64-bit successor to | 47 | The Itanium Processor Family is Intel's 64-bit successor to |
diff --git a/arch/ia64/include/asm/module.h b/arch/ia64/include/asm/module.h index 908eaef42a08..dfba22a872c3 100644 --- a/arch/ia64/include/asm/module.h +++ b/arch/ia64/include/asm/module.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef _ASM_IA64_MODULE_H | 1 | #ifndef _ASM_IA64_MODULE_H |
2 | #define _ASM_IA64_MODULE_H | 2 | #define _ASM_IA64_MODULE_H |
3 | 3 | ||
4 | #include <asm-generic/module.h> | ||
5 | |||
4 | /* | 6 | /* |
5 | * IA-64-specific support for kernel module loader. | 7 | * IA-64-specific support for kernel module loader. |
6 | * | 8 | * |
@@ -29,10 +31,6 @@ struct mod_arch_specific { | |||
29 | unsigned int next_got_entry; /* index of next available got entry */ | 31 | unsigned int next_got_entry; /* index of next available got entry */ |
30 | }; | 32 | }; |
31 | 33 | ||
32 | #define Elf_Shdr Elf64_Shdr | ||
33 | #define Elf_Sym Elf64_Sym | ||
34 | #define Elf_Ehdr Elf64_Ehdr | ||
35 | |||
36 | #define MODULE_PROC_FAMILY "ia64" | 34 | #define MODULE_PROC_FAMILY "ia64" |
37 | #define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY \ | 35 | #define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY \ |
38 | "gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__) | 36 | "gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__) |
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index e875fc3ce9cb..f807721e19a5 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig | |||
@@ -14,6 +14,7 @@ config M32R | |||
14 | select GENERIC_IRQ_SHOW | 14 | select GENERIC_IRQ_SHOW |
15 | select GENERIC_ATOMIC64 | 15 | select GENERIC_ATOMIC64 |
16 | select ARCH_USES_GETTIMEOFFSET | 16 | select ARCH_USES_GETTIMEOFFSET |
17 | select MODULES_USE_ELF_RELA | ||
17 | 18 | ||
18 | config SBUS | 19 | config SBUS |
19 | bool | 20 | bool |
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild index fccd81eddff1..50bbf387b2f8 100644 --- a/arch/m32r/include/asm/Kbuild +++ b/arch/m32r/include/asm/Kbuild | |||
@@ -2,3 +2,4 @@ include include/asm-generic/Kbuild.asm | |||
2 | 2 | ||
3 | generic-y += clkdev.h | 3 | generic-y += clkdev.h |
4 | generic-y += exec.h | 4 | generic-y += exec.h |
5 | generic-y += module.h | ||
diff --git a/arch/m32r/include/asm/module.h b/arch/m32r/include/asm/module.h deleted file mode 100644 index eb73ee011215..000000000000 --- a/arch/m32r/include/asm/module.h +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | #ifndef _ASM_M32R_MODULE_H | ||
2 | #define _ASM_M32R_MODULE_H | ||
3 | |||
4 | struct mod_arch_specific { }; | ||
5 | |||
6 | #define Elf_Shdr Elf32_Shdr | ||
7 | #define Elf_Sym Elf32_Sym | ||
8 | #define Elf_Ehdr Elf32_Ehdr | ||
9 | |||
10 | #endif /* _ASM_M32R_MODULE_H */ | ||
diff --git a/arch/m32r/kernel/module.c b/arch/m32r/kernel/module.c index 3071fe83ffc8..38233b6596b6 100644 --- a/arch/m32r/kernel/module.c +++ b/arch/m32r/kernel/module.c | |||
@@ -201,18 +201,3 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, | |||
201 | } | 201 | } |
202 | return 0; | 202 | return 0; |
203 | } | 203 | } |
204 | |||
205 | int apply_relocate(Elf32_Shdr *sechdrs, | ||
206 | const char *strtab, | ||
207 | unsigned int symindex, | ||
208 | unsigned int relsec, | ||
209 | struct module *me) | ||
210 | { | ||
211 | #if 0 | ||
212 | printk(KERN_ERR "module %s: REL RELOCATION unsupported\n", | ||
213 | me->name); | ||
214 | return -ENOEXEC; | ||
215 | #endif | ||
216 | return 0; | ||
217 | |||
218 | } | ||
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 76fd6e2f71da..e7c161433eae 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig | |||
@@ -16,6 +16,9 @@ config M68K | |||
16 | select ARCH_WANT_IPC_PARSE_VERSION | 16 | select ARCH_WANT_IPC_PARSE_VERSION |
17 | select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE | 17 | select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE |
18 | select GENERIC_KERNEL_THREAD | 18 | select GENERIC_KERNEL_THREAD |
19 | select HAVE_MOD_ARCH_SPECIFIC | ||
20 | select MODULES_USE_ELF_REL | ||
21 | select MODULES_USE_ELF_RELA | ||
19 | 22 | ||
20 | config RWSEM_GENERIC_SPINLOCK | 23 | config RWSEM_GENERIC_SPINLOCK |
21 | bool | 24 | bool |
diff --git a/arch/m68k/include/asm/module.h b/arch/m68k/include/asm/module.h index edffe66b7f49..8b58fce843dd 100644 --- a/arch/m68k/include/asm/module.h +++ b/arch/m68k/include/asm/module.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef _ASM_M68K_MODULE_H | 1 | #ifndef _ASM_M68K_MODULE_H |
2 | #define _ASM_M68K_MODULE_H | 2 | #define _ASM_M68K_MODULE_H |
3 | 3 | ||
4 | #include <asm-generic/module.h> | ||
5 | |||
4 | enum m68k_fixup_type { | 6 | enum m68k_fixup_type { |
5 | m68k_fixup_memoffset, | 7 | m68k_fixup_memoffset, |
6 | m68k_fixup_vnode_shift, | 8 | m68k_fixup_vnode_shift, |
@@ -36,8 +38,4 @@ struct module; | |||
36 | extern void module_fixup(struct module *mod, struct m68k_fixup_info *start, | 38 | extern void module_fixup(struct module *mod, struct m68k_fixup_info *start, |
37 | struct m68k_fixup_info *end); | 39 | struct m68k_fixup_info *end); |
38 | 40 | ||
39 | #define Elf_Shdr Elf32_Shdr | ||
40 | #define Elf_Sym Elf32_Sym | ||
41 | #define Elf_Ehdr Elf32_Ehdr | ||
42 | |||
43 | #endif /* _ASM_M68K_MODULE_H */ | 41 | #endif /* _ASM_M68K_MODULE_H */ |
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index 53fd94ab60f0..4cba7439f9de 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig | |||
@@ -25,6 +25,7 @@ config MICROBLAZE | |||
25 | select GENERIC_CPU_DEVICES | 25 | select GENERIC_CPU_DEVICES |
26 | select GENERIC_ATOMIC64 | 26 | select GENERIC_ATOMIC64 |
27 | select GENERIC_CLOCKEVENTS | 27 | select GENERIC_CLOCKEVENTS |
28 | select MODULES_USE_ELF_RELA | ||
28 | 29 | ||
29 | config SWAP | 30 | config SWAP |
30 | def_bool n | 31 | def_bool n |
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 35453eaeffb5..aae16cdfe306 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -37,6 +37,9 @@ config MIPS | |||
37 | select BUILDTIME_EXTABLE_SORT | 37 | select BUILDTIME_EXTABLE_SORT |
38 | select GENERIC_CLOCKEVENTS | 38 | select GENERIC_CLOCKEVENTS |
39 | select GENERIC_CMOS_UPDATE | 39 | select GENERIC_CMOS_UPDATE |
40 | select HAVE_MOD_ARCH_SPECIFIC | ||
41 | select MODULES_USE_ELF_REL | ||
42 | select MODULES_USE_ELF_RELA if 64BIT | ||
40 | 43 | ||
41 | menu "Machine selection" | 44 | menu "Machine selection" |
42 | 45 | ||
diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h index dca8bce8c7ab..26137da1c713 100644 --- a/arch/mips/include/asm/module.h +++ b/arch/mips/include/asm/module.h | |||
@@ -35,11 +35,14 @@ typedef struct { | |||
35 | } Elf64_Mips_Rela; | 35 | } Elf64_Mips_Rela; |
36 | 36 | ||
37 | #ifdef CONFIG_32BIT | 37 | #ifdef CONFIG_32BIT |
38 | |||
39 | #define Elf_Shdr Elf32_Shdr | 38 | #define Elf_Shdr Elf32_Shdr |
40 | #define Elf_Sym Elf32_Sym | 39 | #define Elf_Sym Elf32_Sym |
41 | #define Elf_Ehdr Elf32_Ehdr | 40 | #define Elf_Ehdr Elf32_Ehdr |
42 | #define Elf_Addr Elf32_Addr | 41 | #define Elf_Addr Elf32_Addr |
42 | #define Elf_Rel Elf32_Rel | ||
43 | #define Elf_Rela Elf32_Rela | ||
44 | #define ELF_R_TYPE(X) ELF32_R_TYPE(X) | ||
45 | #define ELF_R_SYM(X) ELF32_R_SYM(X) | ||
43 | 46 | ||
44 | #define Elf_Mips_Rel Elf32_Rel | 47 | #define Elf_Mips_Rel Elf32_Rel |
45 | #define Elf_Mips_Rela Elf32_Rela | 48 | #define Elf_Mips_Rela Elf32_Rela |
@@ -50,11 +53,14 @@ typedef struct { | |||
50 | #endif | 53 | #endif |
51 | 54 | ||
52 | #ifdef CONFIG_64BIT | 55 | #ifdef CONFIG_64BIT |
53 | |||
54 | #define Elf_Shdr Elf64_Shdr | 56 | #define Elf_Shdr Elf64_Shdr |
55 | #define Elf_Sym Elf64_Sym | 57 | #define Elf_Sym Elf64_Sym |
56 | #define Elf_Ehdr Elf64_Ehdr | 58 | #define Elf_Ehdr Elf64_Ehdr |
57 | #define Elf_Addr Elf64_Addr | 59 | #define Elf_Addr Elf64_Addr |
60 | #define Elf_Rel Elf64_Rel | ||
61 | #define Elf_Rela Elf64_Rela | ||
62 | #define ELF_R_TYPE(X) ELF64_R_TYPE(X) | ||
63 | #define ELF_R_SYM(X) ELF64_R_SYM(X) | ||
58 | 64 | ||
59 | #define Elf_Mips_Rel Elf64_Mips_Rel | 65 | #define Elf_Mips_Rel Elf64_Mips_Rel |
60 | #define Elf_Mips_Rela Elf64_Mips_Rela | 66 | #define Elf_Mips_Rela Elf64_Mips_Rela |
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index d6c2a7476bac..414c26920df8 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile | |||
@@ -31,6 +31,7 @@ obj-$(CONFIG_SYNC_R4K) += sync-r4k.o | |||
31 | 31 | ||
32 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 32 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
33 | obj-$(CONFIG_MODULES) += mips_ksyms.o module.o | 33 | obj-$(CONFIG_MODULES) += mips_ksyms.o module.o |
34 | obj-$(CONFIG_MODULES_USE_ELF_RELA) += module-rela.o | ||
34 | 35 | ||
35 | obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o | 36 | obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o |
36 | 37 | ||
diff --git a/arch/mips/kernel/module-rela.c b/arch/mips/kernel/module-rela.c new file mode 100644 index 000000000000..61d60028b888 --- /dev/null +++ b/arch/mips/kernel/module-rela.c | |||
@@ -0,0 +1,145 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License as published by | ||
4 | * the Free Software Foundation; either version 2 of the License, or | ||
5 | * (at your option) any later version. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
15 | * | ||
16 | * Copyright (C) 2001 Rusty Russell. | ||
17 | * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org) | ||
18 | * Copyright (C) 2005 Thiemo Seufer | ||
19 | */ | ||
20 | |||
21 | #include <linux/elf.h> | ||
22 | #include <linux/err.h> | ||
23 | #include <linux/errno.h> | ||
24 | #include <linux/moduleloader.h> | ||
25 | |||
26 | extern int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v); | ||
27 | |||
28 | static int apply_r_mips_32_rela(struct module *me, u32 *location, Elf_Addr v) | ||
29 | { | ||
30 | *location = v; | ||
31 | |||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) | ||
36 | { | ||
37 | if (v % 4) { | ||
38 | pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n", | ||
39 | me->name); | ||
40 | return -ENOEXEC; | ||
41 | } | ||
42 | |||
43 | if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { | ||
44 | printk(KERN_ERR | ||
45 | "module %s: relocation overflow\n", | ||
46 | me->name); | ||
47 | return -ENOEXEC; | ||
48 | } | ||
49 | |||
50 | *location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff); | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int apply_r_mips_hi16_rela(struct module *me, u32 *location, Elf_Addr v) | ||
56 | { | ||
57 | *location = (*location & 0xffff0000) | | ||
58 | ((((long long) v + 0x8000LL) >> 16) & 0xffff); | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static int apply_r_mips_lo16_rela(struct module *me, u32 *location, Elf_Addr v) | ||
64 | { | ||
65 | *location = (*location & 0xffff0000) | (v & 0xffff); | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static int apply_r_mips_64_rela(struct module *me, u32 *location, Elf_Addr v) | ||
71 | { | ||
72 | *(Elf_Addr *)location = v; | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int apply_r_mips_higher_rela(struct module *me, u32 *location, | ||
78 | Elf_Addr v) | ||
79 | { | ||
80 | *location = (*location & 0xffff0000) | | ||
81 | ((((long long) v + 0x80008000LL) >> 32) & 0xffff); | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static int apply_r_mips_highest_rela(struct module *me, u32 *location, | ||
87 | Elf_Addr v) | ||
88 | { | ||
89 | *location = (*location & 0xffff0000) | | ||
90 | ((((long long) v + 0x800080008000LL) >> 48) & 0xffff); | ||
91 | |||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static int (*reloc_handlers_rela[]) (struct module *me, u32 *location, | ||
96 | Elf_Addr v) = { | ||
97 | [R_MIPS_NONE] = apply_r_mips_none, | ||
98 | [R_MIPS_32] = apply_r_mips_32_rela, | ||
99 | [R_MIPS_26] = apply_r_mips_26_rela, | ||
100 | [R_MIPS_HI16] = apply_r_mips_hi16_rela, | ||
101 | [R_MIPS_LO16] = apply_r_mips_lo16_rela, | ||
102 | [R_MIPS_64] = apply_r_mips_64_rela, | ||
103 | [R_MIPS_HIGHER] = apply_r_mips_higher_rela, | ||
104 | [R_MIPS_HIGHEST] = apply_r_mips_highest_rela | ||
105 | }; | ||
106 | |||
107 | int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, | ||
108 | unsigned int symindex, unsigned int relsec, | ||
109 | struct module *me) | ||
110 | { | ||
111 | Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr; | ||
112 | Elf_Sym *sym; | ||
113 | u32 *location; | ||
114 | unsigned int i; | ||
115 | Elf_Addr v; | ||
116 | int res; | ||
117 | |||
118 | pr_debug("Applying relocate section %u to %u\n", relsec, | ||
119 | sechdrs[relsec].sh_info); | ||
120 | |||
121 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { | ||
122 | /* This is where to make the change */ | ||
123 | location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr | ||
124 | + rel[i].r_offset; | ||
125 | /* This is the symbol it is referring to */ | ||
126 | sym = (Elf_Sym *)sechdrs[symindex].sh_addr | ||
127 | + ELF_MIPS_R_SYM(rel[i]); | ||
128 | if (IS_ERR_VALUE(sym->st_value)) { | ||
129 | /* Ignore unresolved weak symbol */ | ||
130 | if (ELF_ST_BIND(sym->st_info) == STB_WEAK) | ||
131 | continue; | ||
132 | printk(KERN_WARNING "%s: Unknown symbol %s\n", | ||
133 | me->name, strtab + sym->st_name); | ||
134 | return -ENOENT; | ||
135 | } | ||
136 | |||
137 | v = sym->st_value + rel[i].r_addend; | ||
138 | |||
139 | res = reloc_handlers_rela[ELF_MIPS_R_TYPE(rel[i])](me, location, v); | ||
140 | if (res) | ||
141 | return res; | ||
142 | } | ||
143 | |||
144 | return 0; | ||
145 | } | ||
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c index 4f8c3cba8c0c..07ff5812ffaf 100644 --- a/arch/mips/kernel/module.c +++ b/arch/mips/kernel/module.c | |||
@@ -51,7 +51,7 @@ void *module_alloc(unsigned long size) | |||
51 | } | 51 | } |
52 | #endif | 52 | #endif |
53 | 53 | ||
54 | static int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v) | 54 | int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v) |
55 | { | 55 | { |
56 | return 0; | 56 | return 0; |
57 | } | 57 | } |
@@ -63,13 +63,6 @@ static int apply_r_mips_32_rel(struct module *me, u32 *location, Elf_Addr v) | |||
63 | return 0; | 63 | return 0; |
64 | } | 64 | } |
65 | 65 | ||
66 | static int apply_r_mips_32_rela(struct module *me, u32 *location, Elf_Addr v) | ||
67 | { | ||
68 | *location = v; | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) | 66 | static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) |
74 | { | 67 | { |
75 | if (v % 4) { | 68 | if (v % 4) { |
@@ -91,26 +84,6 @@ static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) | |||
91 | return 0; | 84 | return 0; |
92 | } | 85 | } |
93 | 86 | ||
94 | static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) | ||
95 | { | ||
96 | if (v % 4) { | ||
97 | pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n", | ||
98 | me->name); | ||
99 | return -ENOEXEC; | ||
100 | } | ||
101 | |||
102 | if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { | ||
103 | printk(KERN_ERR | ||
104 | "module %s: relocation overflow\n", | ||
105 | me->name); | ||
106 | return -ENOEXEC; | ||
107 | } | ||
108 | |||
109 | *location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) | 87 | static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) |
115 | { | 88 | { |
116 | struct mips_hi16 *n; | 89 | struct mips_hi16 *n; |
@@ -132,14 +105,6 @@ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) | |||
132 | return 0; | 105 | return 0; |
133 | } | 106 | } |
134 | 107 | ||
135 | static int apply_r_mips_hi16_rela(struct module *me, u32 *location, Elf_Addr v) | ||
136 | { | ||
137 | *location = (*location & 0xffff0000) | | ||
138 | ((((long long) v + 0x8000LL) >> 16) & 0xffff); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static void free_relocation_chain(struct mips_hi16 *l) | 108 | static void free_relocation_chain(struct mips_hi16 *l) |
144 | { | 109 | { |
145 | struct mips_hi16 *next; | 110 | struct mips_hi16 *next; |
@@ -217,38 +182,6 @@ out_danger: | |||
217 | return -ENOEXEC; | 182 | return -ENOEXEC; |
218 | } | 183 | } |
219 | 184 | ||
220 | static int apply_r_mips_lo16_rela(struct module *me, u32 *location, Elf_Addr v) | ||
221 | { | ||
222 | *location = (*location & 0xffff0000) | (v & 0xffff); | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int apply_r_mips_64_rela(struct module *me, u32 *location, Elf_Addr v) | ||
228 | { | ||
229 | *(Elf_Addr *)location = v; | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static int apply_r_mips_higher_rela(struct module *me, u32 *location, | ||
235 | Elf_Addr v) | ||
236 | { | ||
237 | *location = (*location & 0xffff0000) | | ||
238 | ((((long long) v + 0x80008000LL) >> 32) & 0xffff); | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int apply_r_mips_highest_rela(struct module *me, u32 *location, | ||
244 | Elf_Addr v) | ||
245 | { | ||
246 | *location = (*location & 0xffff0000) | | ||
247 | ((((long long) v + 0x800080008000LL) >> 48) & 0xffff); | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static int (*reloc_handlers_rel[]) (struct module *me, u32 *location, | 185 | static int (*reloc_handlers_rel[]) (struct module *me, u32 *location, |
253 | Elf_Addr v) = { | 186 | Elf_Addr v) = { |
254 | [R_MIPS_NONE] = apply_r_mips_none, | 187 | [R_MIPS_NONE] = apply_r_mips_none, |
@@ -258,18 +191,6 @@ static int (*reloc_handlers_rel[]) (struct module *me, u32 *location, | |||
258 | [R_MIPS_LO16] = apply_r_mips_lo16_rel | 191 | [R_MIPS_LO16] = apply_r_mips_lo16_rel |
259 | }; | 192 | }; |
260 | 193 | ||
261 | static int (*reloc_handlers_rela[]) (struct module *me, u32 *location, | ||
262 | Elf_Addr v) = { | ||
263 | [R_MIPS_NONE] = apply_r_mips_none, | ||
264 | [R_MIPS_32] = apply_r_mips_32_rela, | ||
265 | [R_MIPS_26] = apply_r_mips_26_rela, | ||
266 | [R_MIPS_HI16] = apply_r_mips_hi16_rela, | ||
267 | [R_MIPS_LO16] = apply_r_mips_lo16_rela, | ||
268 | [R_MIPS_64] = apply_r_mips_64_rela, | ||
269 | [R_MIPS_HIGHER] = apply_r_mips_higher_rela, | ||
270 | [R_MIPS_HIGHEST] = apply_r_mips_highest_rela | ||
271 | }; | ||
272 | |||
273 | int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, | 194 | int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, |
274 | unsigned int symindex, unsigned int relsec, | 195 | unsigned int symindex, unsigned int relsec, |
275 | struct module *me) | 196 | struct module *me) |
@@ -324,46 +245,6 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, | |||
324 | return 0; | 245 | return 0; |
325 | } | 246 | } |
326 | 247 | ||
327 | int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, | ||
328 | unsigned int symindex, unsigned int relsec, | ||
329 | struct module *me) | ||
330 | { | ||
331 | Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr; | ||
332 | Elf_Sym *sym; | ||
333 | u32 *location; | ||
334 | unsigned int i; | ||
335 | Elf_Addr v; | ||
336 | int res; | ||
337 | |||
338 | pr_debug("Applying relocate section %u to %u\n", relsec, | ||
339 | sechdrs[relsec].sh_info); | ||
340 | |||
341 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { | ||
342 | /* This is where to make the change */ | ||
343 | location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr | ||
344 | + rel[i].r_offset; | ||
345 | /* This is the symbol it is referring to */ | ||
346 | sym = (Elf_Sym *)sechdrs[symindex].sh_addr | ||
347 | + ELF_MIPS_R_SYM(rel[i]); | ||
348 | if (IS_ERR_VALUE(sym->st_value)) { | ||
349 | /* Ignore unresolved weak symbol */ | ||
350 | if (ELF_ST_BIND(sym->st_info) == STB_WEAK) | ||
351 | continue; | ||
352 | printk(KERN_WARNING "%s: Unknown symbol %s\n", | ||
353 | me->name, strtab + sym->st_name); | ||
354 | return -ENOENT; | ||
355 | } | ||
356 | |||
357 | v = sym->st_value + rel[i].r_addend; | ||
358 | |||
359 | res = reloc_handlers_rela[ELF_MIPS_R_TYPE(rel[i])](me, location, v); | ||
360 | if (res) | ||
361 | return res; | ||
362 | } | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | /* Given an address, look for it in the module exception tables. */ | 248 | /* Given an address, look for it in the module exception tables. */ |
368 | const struct exception_table_entry *search_module_dbetables(unsigned long addr) | 249 | const struct exception_table_entry *search_module_dbetables(unsigned long addr) |
369 | { | 250 | { |
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index ddbdc33471a8..04669fac117b 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig | |||
@@ -9,6 +9,7 @@ config MN10300 | |||
9 | select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER | 9 | select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER |
10 | select GENERIC_CLOCKEVENTS | 10 | select GENERIC_CLOCKEVENTS |
11 | select GENERIC_KERNEL_THREAD | 11 | select GENERIC_KERNEL_THREAD |
12 | select MODULES_USE_ELF_RELA | ||
12 | 13 | ||
13 | config AM33_2 | 14 | config AM33_2 |
14 | def_bool n | 15 | def_bool n |
diff --git a/arch/mn10300/include/asm/module.h b/arch/mn10300/include/asm/module.h index 5d7057d01494..6571103b0518 100644 --- a/arch/mn10300/include/asm/module.h +++ b/arch/mn10300/include/asm/module.h | |||
@@ -12,12 +12,7 @@ | |||
12 | #ifndef _ASM_MODULE_H | 12 | #ifndef _ASM_MODULE_H |
13 | #define _ASM_MODULE_H | 13 | #define _ASM_MODULE_H |
14 | 14 | ||
15 | struct mod_arch_specific { | 15 | #include <asm-generic/module.h> |
16 | }; | ||
17 | |||
18 | #define Elf_Shdr Elf32_Shdr | ||
19 | #define Elf_Sym Elf32_Sym | ||
20 | #define Elf_Ehdr Elf32_Ehdr | ||
21 | 16 | ||
22 | /* | 17 | /* |
23 | * Include the MN10300 architecture version. | 18 | * Include the MN10300 architecture version. |
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig index 49765b53f637..05f2ba41ff1a 100644 --- a/arch/openrisc/Kconfig +++ b/arch/openrisc/Kconfig | |||
@@ -21,6 +21,7 @@ config OPENRISC | |||
21 | select GENERIC_CLOCKEVENTS | 21 | select GENERIC_CLOCKEVENTS |
22 | select GENERIC_STRNCPY_FROM_USER | 22 | select GENERIC_STRNCPY_FROM_USER |
23 | select GENERIC_STRNLEN_USER | 23 | select GENERIC_STRNLEN_USER |
24 | select MODULES_USE_ELF_RELA | ||
24 | 25 | ||
25 | config MMU | 26 | config MMU |
26 | def_bool y | 27 | def_bool y |
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index b87438bb3384..11def45b98c5 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig | |||
@@ -20,6 +20,8 @@ config PARISC | |||
20 | select ARCH_HAVE_NMI_SAFE_CMPXCHG | 20 | select ARCH_HAVE_NMI_SAFE_CMPXCHG |
21 | select GENERIC_SMP_IDLE_THREAD | 21 | select GENERIC_SMP_IDLE_THREAD |
22 | select GENERIC_STRNCPY_FROM_USER | 22 | select GENERIC_STRNCPY_FROM_USER |
23 | select HAVE_MOD_ARCH_SPECIFIC | ||
24 | select MODULES_USE_ELF_RELA | ||
23 | 25 | ||
24 | help | 26 | help |
25 | The PA-RISC microprocessor is designed by Hewlett-Packard and used | 27 | The PA-RISC microprocessor is designed by Hewlett-Packard and used |
diff --git a/arch/parisc/include/asm/module.h b/arch/parisc/include/asm/module.h index 1f4123427ea0..bab37e99168a 100644 --- a/arch/parisc/include/asm/module.h +++ b/arch/parisc/include/asm/module.h | |||
@@ -1,21 +1,11 @@ | |||
1 | #ifndef _ASM_PARISC_MODULE_H | 1 | #ifndef _ASM_PARISC_MODULE_H |
2 | #define _ASM_PARISC_MODULE_H | 2 | #define _ASM_PARISC_MODULE_H |
3 | |||
4 | #include <asm-generic/module.h> | ||
5 | |||
3 | /* | 6 | /* |
4 | * This file contains the parisc architecture specific module code. | 7 | * This file contains the parisc architecture specific module code. |
5 | */ | 8 | */ |
6 | #ifdef CONFIG_64BIT | ||
7 | #define Elf_Shdr Elf64_Shdr | ||
8 | #define Elf_Sym Elf64_Sym | ||
9 | #define Elf_Ehdr Elf64_Ehdr | ||
10 | #define Elf_Addr Elf64_Addr | ||
11 | #define Elf_Rela Elf64_Rela | ||
12 | #else | ||
13 | #define Elf_Shdr Elf32_Shdr | ||
14 | #define Elf_Sym Elf32_Sym | ||
15 | #define Elf_Ehdr Elf32_Ehdr | ||
16 | #define Elf_Addr Elf32_Addr | ||
17 | #define Elf_Rela Elf32_Rela | ||
18 | #endif | ||
19 | 9 | ||
20 | struct unwind_table; | 10 | struct unwind_table; |
21 | 11 | ||
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 969f3d9ded91..a902a5c1c76a 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -142,6 +142,8 @@ config PPC | |||
142 | select GENERIC_STRNCPY_FROM_USER | 142 | select GENERIC_STRNCPY_FROM_USER |
143 | select GENERIC_STRNLEN_USER | 143 | select GENERIC_STRNLEN_USER |
144 | select GENERIC_KERNEL_THREAD | 144 | select GENERIC_KERNEL_THREAD |
145 | select HAVE_MOD_ARCH_SPECIFIC | ||
146 | select MODULES_USE_ELF_RELA | ||
145 | 147 | ||
146 | config EARLY_PRINTK | 148 | config EARLY_PRINTK |
147 | bool | 149 | bool |
diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h index 0192a4ee2bc2..c1df590ec444 100644 --- a/arch/powerpc/include/asm/module.h +++ b/arch/powerpc/include/asm/module.h | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/list.h> | 12 | #include <linux/list.h> |
13 | #include <asm/bug.h> | 13 | #include <asm/bug.h> |
14 | #include <asm-generic/module.h> | ||
14 | 15 | ||
15 | 16 | ||
16 | #ifndef __powerpc64__ | 17 | #ifndef __powerpc64__ |
@@ -60,16 +61,10 @@ struct mod_arch_specific { | |||
60 | */ | 61 | */ |
61 | 62 | ||
62 | #ifdef __powerpc64__ | 63 | #ifdef __powerpc64__ |
63 | # define Elf_Shdr Elf64_Shdr | ||
64 | # define Elf_Sym Elf64_Sym | ||
65 | # define Elf_Ehdr Elf64_Ehdr | ||
66 | # ifdef MODULE | 64 | # ifdef MODULE |
67 | asm(".section .stubs,\"ax\",@nobits; .align 3; .previous"); | 65 | asm(".section .stubs,\"ax\",@nobits; .align 3; .previous"); |
68 | # endif | 66 | # endif |
69 | #else | 67 | #else |
70 | # define Elf_Shdr Elf32_Shdr | ||
71 | # define Elf_Sym Elf32_Sym | ||
72 | # define Elf_Ehdr Elf32_Ehdr | ||
73 | # ifdef MODULE | 68 | # ifdef MODULE |
74 | asm(".section .plt,\"ax\",@nobits; .align 3; .previous"); | 69 | asm(".section .plt,\"ax\",@nobits; .align 3; .previous"); |
75 | asm(".section .init.plt,\"ax\",@nobits; .align 3; .previous"); | 70 | asm(".section .init.plt,\"ax\",@nobits; .align 3; .previous"); |
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index e5dac1236185..3f3d9ca7a5b6 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -136,6 +136,8 @@ config S390 | |||
136 | select KTIME_SCALAR if 32BIT | 136 | select KTIME_SCALAR if 32BIT |
137 | select HAVE_ARCH_SECCOMP_FILTER | 137 | select HAVE_ARCH_SECCOMP_FILTER |
138 | select GENERIC_KERNEL_THREAD | 138 | select GENERIC_KERNEL_THREAD |
139 | select HAVE_MOD_ARCH_SPECIFIC | ||
140 | select MODULES_USE_ELF_RELA | ||
139 | 141 | ||
140 | config SCHED_OMIT_FRAME_POINTER | 142 | config SCHED_OMIT_FRAME_POINTER |
141 | def_bool y | 143 | def_bool y |
diff --git a/arch/s390/include/asm/module.h b/arch/s390/include/asm/module.h index f0b6b26b6e59..df1f861a848a 100644 --- a/arch/s390/include/asm/module.h +++ b/arch/s390/include/asm/module.h | |||
@@ -1,5 +1,8 @@ | |||
1 | #ifndef _ASM_S390_MODULE_H | 1 | #ifndef _ASM_S390_MODULE_H |
2 | #define _ASM_S390_MODULE_H | 2 | #define _ASM_S390_MODULE_H |
3 | |||
4 | #include <asm-generic/module.h> | ||
5 | |||
3 | /* | 6 | /* |
4 | * This file contains the s390 architecture specific module code. | 7 | * This file contains the s390 architecture specific module code. |
5 | */ | 8 | */ |
@@ -28,19 +31,4 @@ struct mod_arch_specific | |||
28 | struct mod_arch_syminfo *syminfo; | 31 | struct mod_arch_syminfo *syminfo; |
29 | }; | 32 | }; |
30 | 33 | ||
31 | #ifdef CONFIG_64BIT | ||
32 | #define ElfW(x) Elf64_ ## x | ||
33 | #define ELFW(x) ELF64_ ## x | ||
34 | #else | ||
35 | #define ElfW(x) Elf32_ ## x | ||
36 | #define ELFW(x) ELF32_ ## x | ||
37 | #endif | ||
38 | |||
39 | #define Elf_Addr ElfW(Addr) | ||
40 | #define Elf_Rela ElfW(Rela) | ||
41 | #define Elf_Shdr ElfW(Shdr) | ||
42 | #define Elf_Sym ElfW(Sym) | ||
43 | #define Elf_Ehdr ElfW(Ehdr) | ||
44 | #define ELF_R_SYM ELFW(R_SYM) | ||
45 | #define ELF_R_TYPE ELFW(R_TYPE) | ||
46 | #endif /* _ASM_S390_MODULE_H */ | 34 | #endif /* _ASM_S390_MODULE_H */ |
diff --git a/arch/score/Kconfig b/arch/score/Kconfig index 461c23747491..4f93a431a45a 100644 --- a/arch/score/Kconfig +++ b/arch/score/Kconfig | |||
@@ -11,6 +11,8 @@ config SCORE | |||
11 | select ARCH_DISCARD_MEMBLOCK | 11 | select ARCH_DISCARD_MEMBLOCK |
12 | select GENERIC_CPU_DEVICES | 12 | select GENERIC_CPU_DEVICES |
13 | select GENERIC_CLOCKEVENTS | 13 | select GENERIC_CLOCKEVENTS |
14 | select HAVE_MOD_ARCH_SPECIFIC | ||
15 | select MODULES_USE_ELF_REL | ||
14 | 16 | ||
15 | choice | 17 | choice |
16 | prompt "System type" | 18 | prompt "System type" |
diff --git a/arch/score/include/asm/module.h b/arch/score/include/asm/module.h index f0b5dc0bd023..abf395bbfaba 100644 --- a/arch/score/include/asm/module.h +++ b/arch/score/include/asm/module.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <linux/list.h> | 4 | #include <linux/list.h> |
5 | #include <asm/uaccess.h> | 5 | #include <asm/uaccess.h> |
6 | #include <asm-generic/module.h> | ||
6 | 7 | ||
7 | struct mod_arch_specific { | 8 | struct mod_arch_specific { |
8 | /* Data Bus Error exception tables */ | 9 | /* Data Bus Error exception tables */ |
@@ -13,11 +14,6 @@ struct mod_arch_specific { | |||
13 | 14 | ||
14 | typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ | 15 | typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ |
15 | 16 | ||
16 | #define Elf_Shdr Elf32_Shdr | ||
17 | #define Elf_Sym Elf32_Sym | ||
18 | #define Elf_Ehdr Elf32_Ehdr | ||
19 | #define Elf_Addr Elf32_Addr | ||
20 | |||
21 | /* Given an address, look for it in the exception tables. */ | 17 | /* Given an address, look for it in the exception tables. */ |
22 | #ifdef CONFIG_MODULES | 18 | #ifdef CONFIG_MODULES |
23 | const struct exception_table_entry *search_module_dbetables(unsigned long addr); | 19 | const struct exception_table_entry *search_module_dbetables(unsigned long addr); |
diff --git a/arch/score/kernel/module.c b/arch/score/kernel/module.c index 469e3b64e2f2..1378d99baa3d 100644 --- a/arch/score/kernel/module.c +++ b/arch/score/kernel/module.c | |||
@@ -125,16 +125,6 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, | |||
125 | return 0; | 125 | return 0; |
126 | } | 126 | } |
127 | 127 | ||
128 | int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, | ||
129 | unsigned int symindex, unsigned int relsec, | ||
130 | struct module *me) | ||
131 | { | ||
132 | /* Non-standard return value... most other arch's return -ENOEXEC | ||
133 | * for an unsupported relocation variant | ||
134 | */ | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | /* Given an address, look for it in the module exception tables. */ | 128 | /* Given an address, look for it in the module exception tables. */ |
139 | const struct exception_table_entry *search_module_dbetables(unsigned long addr) | 129 | const struct exception_table_entry *search_module_dbetables(unsigned long addr) |
140 | { | 130 | { |
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 3b3e27a3ff2c..babc2b826c5c 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
@@ -38,6 +38,8 @@ config SUPERH | |||
38 | select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST | 38 | select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST |
39 | select GENERIC_STRNCPY_FROM_USER | 39 | select GENERIC_STRNCPY_FROM_USER |
40 | select GENERIC_STRNLEN_USER | 40 | select GENERIC_STRNLEN_USER |
41 | select HAVE_MOD_ARCH_SPECIFIC if DWARF_UNWINDER | ||
42 | select MODULES_USE_ELF_RELA | ||
41 | help | 43 | help |
42 | The SuperH is a RISC processor targeted for use in embedded systems | 44 | The SuperH is a RISC processor targeted for use in embedded systems |
43 | and consumer electronics; it was also used in the Sega Dreamcast | 45 | and consumer electronics; it was also used in the Sega Dreamcast |
diff --git a/arch/sh/include/asm/module.h b/arch/sh/include/asm/module.h index b7927de86f9f..81300d8b5448 100644 --- a/arch/sh/include/asm/module.h +++ b/arch/sh/include/asm/module.h | |||
@@ -1,21 +1,13 @@ | |||
1 | #ifndef _ASM_SH_MODULE_H | 1 | #ifndef _ASM_SH_MODULE_H |
2 | #define _ASM_SH_MODULE_H | 2 | #define _ASM_SH_MODULE_H |
3 | 3 | ||
4 | struct mod_arch_specific { | 4 | #include <asm-generic/module.h> |
5 | |||
5 | #ifdef CONFIG_DWARF_UNWINDER | 6 | #ifdef CONFIG_DWARF_UNWINDER |
7 | struct mod_arch_specific { | ||
6 | struct list_head fde_list; | 8 | struct list_head fde_list; |
7 | struct list_head cie_list; | 9 | struct list_head cie_list; |
8 | #endif | ||
9 | }; | 10 | }; |
10 | |||
11 | #ifdef CONFIG_64BIT | ||
12 | #define Elf_Shdr Elf64_Shdr | ||
13 | #define Elf_Sym Elf64_Sym | ||
14 | #define Elf_Ehdr Elf64_Ehdr | ||
15 | #else | ||
16 | #define Elf_Shdr Elf32_Shdr | ||
17 | #define Elf_Sym Elf32_Sym | ||
18 | #define Elf_Ehdr Elf32_Ehdr | ||
19 | #endif | 11 | #endif |
20 | 12 | ||
21 | #ifdef CONFIG_CPU_LITTLE_ENDIAN | 13 | #ifdef CONFIG_CPU_LITTLE_ENDIAN |
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 91c780c973ba..b6b442b0d793 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -39,6 +39,7 @@ config SPARC | |||
39 | select GENERIC_CLOCKEVENTS | 39 | select GENERIC_CLOCKEVENTS |
40 | select GENERIC_STRNCPY_FROM_USER | 40 | select GENERIC_STRNCPY_FROM_USER |
41 | select GENERIC_STRNLEN_USER | 41 | select GENERIC_STRNLEN_USER |
42 | select MODULES_USE_ELF_RELA | ||
42 | 43 | ||
43 | config SPARC32 | 44 | config SPARC32 |
44 | def_bool !64BIT | 45 | def_bool !64BIT |
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index 10d54e5e37f5..645a58da0e86 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild | |||
@@ -7,4 +7,5 @@ generic-y += exec.h | |||
7 | generic-y += local64.h | 7 | generic-y += local64.h |
8 | generic-y += irq_regs.h | 8 | generic-y += irq_regs.h |
9 | generic-y += local.h | 9 | generic-y += local.h |
10 | generic-y += module.h | ||
10 | generic-y += word-at-a-time.h | 11 | generic-y += word-at-a-time.h |
diff --git a/arch/sparc/include/asm/module.h b/arch/sparc/include/asm/module.h deleted file mode 100644 index ff8e02d80334..000000000000 --- a/arch/sparc/include/asm/module.h +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | #ifndef __SPARC_MODULE_H | ||
2 | #define __SPARC_MODULE_H | ||
3 | struct mod_arch_specific { }; | ||
4 | |||
5 | /* | ||
6 | * Use some preprocessor magic to define the correct symbol | ||
7 | * for sparc32 and sparc64. | ||
8 | * Elf_Addr becomes Elf32_Addr for sparc32 and Elf64_Addr for sparc64 | ||
9 | */ | ||
10 | #define ___ELF(a, b, c) a##b##c | ||
11 | #define __ELF(a, b, c) ___ELF(a, b, c) | ||
12 | #define _Elf(t) __ELF(Elf, CONFIG_BITS, t) | ||
13 | #define _ELF(t) __ELF(ELF, CONFIG_BITS, t) | ||
14 | |||
15 | #define Elf_Shdr _Elf(_Shdr) | ||
16 | #define Elf_Sym _Elf(_Sym) | ||
17 | #define Elf_Ehdr _Elf(_Ehdr) | ||
18 | #define Elf_Rela _Elf(_Rela) | ||
19 | #define Elf_Addr _Elf(_Addr) | ||
20 | |||
21 | #define ELF_R_SYM _ELF(_R_SYM) | ||
22 | #define ELF_R_TYPE _ELF(_R_TYPE) | ||
23 | |||
24 | #endif /* __SPARC_MODULE_H */ | ||
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig index dc46490adca0..875d008828b8 100644 --- a/arch/tile/Kconfig +++ b/arch/tile/Kconfig | |||
@@ -20,6 +20,7 @@ config TILE | |||
20 | select SYS_HYPERVISOR | 20 | select SYS_HYPERVISOR |
21 | select ARCH_HAVE_NMI_SAFE_CMPXCHG | 21 | select ARCH_HAVE_NMI_SAFE_CMPXCHG |
22 | select GENERIC_CLOCKEVENTS | 22 | select GENERIC_CLOCKEVENTS |
23 | select MODULES_USE_ELF_RELA | ||
23 | 24 | ||
24 | # FIXME: investigate whether we need/want these options. | 25 | # FIXME: investigate whether we need/want these options. |
25 | # select HAVE_IOREMAP_PROT | 26 | # select HAVE_IOREMAP_PROT |
diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig index 35ee2bf66354..e5c5473e69ce 100644 --- a/arch/unicore32/Kconfig +++ b/arch/unicore32/Kconfig | |||
@@ -15,6 +15,7 @@ config UNICORE32 | |||
15 | select GENERIC_IRQ_SHOW | 15 | select GENERIC_IRQ_SHOW |
16 | select ARCH_WANT_FRAME_POINTERS | 16 | select ARCH_WANT_FRAME_POINTERS |
17 | select GENERIC_IOMAP | 17 | select GENERIC_IOMAP |
18 | select MODULES_USE_ELF_REL | ||
18 | help | 19 | help |
19 | UniCore-32 is 32-bit Instruction Set Architecture, | 20 | UniCore-32 is 32-bit Instruction Set Architecture, |
20 | including a series of low-power-consumption RISC chip | 21 | including a series of low-power-consumption RISC chip |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 70071b19eb98..46c3bff3ced2 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -110,6 +110,8 @@ config X86 | |||
110 | select HAVE_IRQ_TIME_ACCOUNTING | 110 | select HAVE_IRQ_TIME_ACCOUNTING |
111 | select GENERIC_KERNEL_THREAD | 111 | select GENERIC_KERNEL_THREAD |
112 | select GENERIC_KERNEL_EXECVE | 112 | select GENERIC_KERNEL_EXECVE |
113 | select MODULES_USE_ELF_REL if X86_32 | ||
114 | select MODULES_USE_ELF_RELA if X86_64 | ||
113 | 115 | ||
114 | config INSTRUCTION_DECODER | 116 | config INSTRUCTION_DECODER |
115 | def_bool y | 117 | def_bool y |
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig index 9fa950df80e5..07611759ce35 100644 --- a/arch/x86/um/Kconfig +++ b/arch/x86/um/Kconfig | |||
@@ -24,9 +24,11 @@ config X86_32 | |||
24 | def_bool !64BIT | 24 | def_bool !64BIT |
25 | select HAVE_AOUT | 25 | select HAVE_AOUT |
26 | select ARCH_WANT_IPC_PARSE_VERSION | 26 | select ARCH_WANT_IPC_PARSE_VERSION |
27 | select MODULES_USE_ELF_REL | ||
27 | 28 | ||
28 | config X86_64 | 29 | config X86_64 |
29 | def_bool 64BIT | 30 | def_bool 64BIT |
31 | select MODULES_USE_ELF_RELA | ||
30 | 32 | ||
31 | config RWSEM_XCHGADD_ALGORITHM | 33 | config RWSEM_XCHGADD_ALGORITHM |
32 | def_bool X86_XADD && 64BIT | 34 | def_bool X86_XADD && 64BIT |
diff --git a/arch/xtensa/include/asm/module.h b/arch/xtensa/include/asm/module.h index d9b34bee4d42..488b40c6f9b9 100644 --- a/arch/xtensa/include/asm/module.h +++ b/arch/xtensa/include/asm/module.h | |||
@@ -13,15 +13,8 @@ | |||
13 | #ifndef _XTENSA_MODULE_H | 13 | #ifndef _XTENSA_MODULE_H |
14 | #define _XTENSA_MODULE_H | 14 | #define _XTENSA_MODULE_H |
15 | 15 | ||
16 | struct mod_arch_specific | ||
17 | { | ||
18 | /* No special elements, yet. */ | ||
19 | }; | ||
20 | |||
21 | #define MODULE_ARCH_VERMAGIC "xtensa-" __stringify(XCHAL_CORE_ID) " " | 16 | #define MODULE_ARCH_VERMAGIC "xtensa-" __stringify(XCHAL_CORE_ID) " " |
22 | 17 | ||
23 | #define Elf_Shdr Elf32_Shdr | 18 | #include <asm-generic/module.h> |
24 | #define Elf_Sym Elf32_Sym | ||
25 | #define Elf_Ehdr Elf32_Ehdr | ||
26 | 19 | ||
27 | #endif /* _XTENSA_MODULE_H */ | 20 | #endif /* _XTENSA_MODULE_H */ |
diff --git a/crypto/Kconfig b/crypto/Kconfig index 50402dc0ea35..6563366bae80 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig | |||
@@ -1216,5 +1216,6 @@ config CRYPTO_USER_API_SKCIPHER | |||
1216 | key cipher algorithms. | 1216 | key cipher algorithms. |
1217 | 1217 | ||
1218 | source "drivers/crypto/Kconfig" | 1218 | source "drivers/crypto/Kconfig" |
1219 | source crypto/asymmetric_keys/Kconfig | ||
1219 | 1220 | ||
1220 | endif # if CRYPTO | 1221 | endif # if CRYPTO |
diff --git a/crypto/Makefile b/crypto/Makefile index a301ad2b258c..8cf61ffe3513 100644 --- a/crypto/Makefile +++ b/crypto/Makefile | |||
@@ -97,3 +97,4 @@ obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o | |||
97 | # | 97 | # |
98 | obj-$(CONFIG_XOR_BLOCKS) += xor.o | 98 | obj-$(CONFIG_XOR_BLOCKS) += xor.o |
99 | obj-$(CONFIG_ASYNC_CORE) += async_tx/ | 99 | obj-$(CONFIG_ASYNC_CORE) += async_tx/ |
100 | obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/ | ||
diff --git a/crypto/asymmetric_keys/.gitignore b/crypto/asymmetric_keys/.gitignore new file mode 100644 index 000000000000..ee328374dba8 --- /dev/null +++ b/crypto/asymmetric_keys/.gitignore | |||
@@ -0,0 +1 @@ | |||
*-asn1.[ch] | |||
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig new file mode 100644 index 000000000000..6d2c2ea12559 --- /dev/null +++ b/crypto/asymmetric_keys/Kconfig | |||
@@ -0,0 +1,38 @@ | |||
1 | menuconfig ASYMMETRIC_KEY_TYPE | ||
2 | tristate "Asymmetric (public-key cryptographic) key type" | ||
3 | depends on KEYS | ||
4 | help | ||
5 | This option provides support for a key type that holds the data for | ||
6 | the asymmetric keys used for public key cryptographic operations such | ||
7 | as encryption, decryption, signature generation and signature | ||
8 | verification. | ||
9 | |||
10 | if ASYMMETRIC_KEY_TYPE | ||
11 | |||
12 | config ASYMMETRIC_PUBLIC_KEY_SUBTYPE | ||
13 | tristate "Asymmetric public-key crypto algorithm subtype" | ||
14 | select MPILIB | ||
15 | help | ||
16 | This option provides support for asymmetric public key type handling. | ||
17 | If signature generation and/or verification are to be used, | ||
18 | appropriate hash algorithms (such as SHA-1) must be available. | ||
19 | ENOPKG will be reported if the requisite algorithm is unavailable. | ||
20 | |||
21 | config PUBLIC_KEY_ALGO_RSA | ||
22 | tristate "RSA public-key algorithm" | ||
23 | depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE | ||
24 | select MPILIB_EXTRA | ||
25 | help | ||
26 | This option enables support for the RSA algorithm (PKCS#1, RFC3447). | ||
27 | |||
28 | config X509_CERTIFICATE_PARSER | ||
29 | tristate "X.509 certificate parser" | ||
30 | depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE | ||
31 | select ASN1 | ||
32 | select OID_REGISTRY | ||
33 | help | ||
34 | This option procides support for parsing X.509 format blobs for key | ||
35 | data and provides the ability to instantiate a crypto key from a | ||
36 | public key packet found inside the certificate. | ||
37 | |||
38 | endif # ASYMMETRIC_KEY_TYPE | ||
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile new file mode 100644 index 000000000000..0727204aab68 --- /dev/null +++ b/crypto/asymmetric_keys/Makefile | |||
@@ -0,0 +1,27 @@ | |||
1 | # | ||
2 | # Makefile for asymmetric cryptographic keys | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o | ||
6 | |||
7 | asymmetric_keys-y := asymmetric_type.o signature.o | ||
8 | |||
9 | obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o | ||
10 | obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o | ||
11 | |||
12 | # | ||
13 | # X.509 Certificate handling | ||
14 | # | ||
15 | obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o | ||
16 | x509_key_parser-y := \ | ||
17 | x509-asn1.o \ | ||
18 | x509_rsakey-asn1.o \ | ||
19 | x509_cert_parser.o \ | ||
20 | x509_public_key.o | ||
21 | |||
22 | $(obj)/x509_cert_parser.o: $(obj)/x509-asn1.h $(obj)/x509_rsakey-asn1.h | ||
23 | $(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h | ||
24 | $(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h | ||
25 | |||
26 | clean-files += x509-asn1.c x509-asn1.h | ||
27 | clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h | ||
diff --git a/crypto/asymmetric_keys/asymmetric_keys.h b/crypto/asymmetric_keys/asymmetric_keys.h new file mode 100644 index 000000000000..515b63430812 --- /dev/null +++ b/crypto/asymmetric_keys/asymmetric_keys.h | |||
@@ -0,0 +1,15 @@ | |||
1 | /* Internal definitions for asymmetric key type | ||
2 | * | ||
3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | static inline const char *asymmetric_key_id(const struct key *key) | ||
13 | { | ||
14 | return key->type_data.p[1]; | ||
15 | } | ||
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c new file mode 100644 index 000000000000..cf807654d221 --- /dev/null +++ b/crypto/asymmetric_keys/asymmetric_type.c | |||
@@ -0,0 +1,274 @@ | |||
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 <keys/asymmetric-parser.h> | ||
15 | #include <linux/seq_file.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include "asymmetric_keys.h" | ||
19 | |||
20 | MODULE_LICENSE("GPL"); | ||
21 | |||
22 | static LIST_HEAD(asymmetric_key_parsers); | ||
23 | static DECLARE_RWSEM(asymmetric_key_parsers_sem); | ||
24 | |||
25 | /* | ||
26 | * Match asymmetric keys on (part of) their name | ||
27 | * We have some shorthand methods for matching keys. We allow: | ||
28 | * | ||
29 | * "<desc>" - request a key by description | ||
30 | * "id:<id>" - request a key matching the ID | ||
31 | * "<subtype>:<id>" - request a key of a subtype | ||
32 | */ | ||
33 | static int asymmetric_key_match(const struct key *key, const void *description) | ||
34 | { | ||
35 | const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); | ||
36 | const char *spec = description; | ||
37 | const char *id, *kid; | ||
38 | ptrdiff_t speclen; | ||
39 | size_t idlen, kidlen; | ||
40 | |||
41 | if (!subtype || !spec || !*spec) | ||
42 | return 0; | ||
43 | |||
44 | /* See if the full key description matches as is */ | ||
45 | if (key->description && strcmp(key->description, description) == 0) | ||
46 | return 1; | ||
47 | |||
48 | /* All tests from here on break the criterion description into a | ||
49 | * specifier, a colon and then an identifier. | ||
50 | */ | ||
51 | id = strchr(spec, ':'); | ||
52 | if (!id) | ||
53 | return 0; | ||
54 | |||
55 | speclen = id - spec; | ||
56 | id++; | ||
57 | |||
58 | /* Anything after here requires a partial match on the ID string */ | ||
59 | kid = asymmetric_key_id(key); | ||
60 | if (!kid) | ||
61 | return 0; | ||
62 | |||
63 | idlen = strlen(id); | ||
64 | kidlen = strlen(kid); | ||
65 | if (idlen > kidlen) | ||
66 | return 0; | ||
67 | |||
68 | kid += kidlen - idlen; | ||
69 | if (strcasecmp(id, kid) != 0) | ||
70 | return 0; | ||
71 | |||
72 | if (speclen == 2 && | ||
73 | memcmp(spec, "id", 2) == 0) | ||
74 | return 1; | ||
75 | |||
76 | if (speclen == subtype->name_len && | ||
77 | memcmp(spec, subtype->name, speclen) == 0) | ||
78 | return 1; | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * Describe the asymmetric key | ||
85 | */ | ||
86 | static void asymmetric_key_describe(const struct key *key, struct seq_file *m) | ||
87 | { | ||
88 | const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); | ||
89 | const char *kid = asymmetric_key_id(key); | ||
90 | size_t n; | ||
91 | |||
92 | seq_puts(m, key->description); | ||
93 | |||
94 | if (subtype) { | ||
95 | seq_puts(m, ": "); | ||
96 | subtype->describe(key, m); | ||
97 | |||
98 | if (kid) { | ||
99 | seq_putc(m, ' '); | ||
100 | n = strlen(kid); | ||
101 | if (n <= 8) | ||
102 | seq_puts(m, kid); | ||
103 | else | ||
104 | seq_puts(m, kid + n - 8); | ||
105 | } | ||
106 | |||
107 | seq_puts(m, " ["); | ||
108 | /* put something here to indicate the key's capabilities */ | ||
109 | seq_putc(m, ']'); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * Preparse a asymmetric payload to get format the contents appropriately for the | ||
115 | * internal payload to cut down on the number of scans of the data performed. | ||
116 | * | ||
117 | * We also generate a proposed description from the contents of the key that | ||
118 | * can be used to name the key if the user doesn't want to provide one. | ||
119 | */ | ||
120 | static int asymmetric_key_preparse(struct key_preparsed_payload *prep) | ||
121 | { | ||
122 | struct asymmetric_key_parser *parser; | ||
123 | int ret; | ||
124 | |||
125 | pr_devel("==>%s()\n", __func__); | ||
126 | |||
127 | if (prep->datalen == 0) | ||
128 | return -EINVAL; | ||
129 | |||
130 | down_read(&asymmetric_key_parsers_sem); | ||
131 | |||
132 | ret = -EBADMSG; | ||
133 | list_for_each_entry(parser, &asymmetric_key_parsers, link) { | ||
134 | pr_debug("Trying parser '%s'\n", parser->name); | ||
135 | |||
136 | ret = parser->parse(prep); | ||
137 | if (ret != -EBADMSG) { | ||
138 | pr_debug("Parser recognised the format (ret %d)\n", | ||
139 | ret); | ||
140 | break; | ||
141 | } | ||
142 | } | ||
143 | |||
144 | up_read(&asymmetric_key_parsers_sem); | ||
145 | pr_devel("<==%s() = %d\n", __func__, ret); | ||
146 | return ret; | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * Clean up the preparse data | ||
151 | */ | ||
152 | static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) | ||
153 | { | ||
154 | struct asymmetric_key_subtype *subtype = prep->type_data[0]; | ||
155 | |||
156 | pr_devel("==>%s()\n", __func__); | ||
157 | |||
158 | if (subtype) { | ||
159 | subtype->destroy(prep->payload); | ||
160 | module_put(subtype->owner); | ||
161 | } | ||
162 | kfree(prep->type_data[1]); | ||
163 | kfree(prep->description); | ||
164 | } | ||
165 | |||
166 | /* | ||
167 | * Instantiate a asymmetric_key defined key. The key was preparsed, so we just | ||
168 | * have to transfer the data here. | ||
169 | */ | ||
170 | static int asymmetric_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | ||
171 | { | ||
172 | int ret; | ||
173 | |||
174 | pr_devel("==>%s()\n", __func__); | ||
175 | |||
176 | ret = key_payload_reserve(key, prep->quotalen); | ||
177 | if (ret == 0) { | ||
178 | key->type_data.p[0] = prep->type_data[0]; | ||
179 | key->type_data.p[1] = prep->type_data[1]; | ||
180 | key->payload.data = prep->payload; | ||
181 | prep->type_data[0] = NULL; | ||
182 | prep->type_data[1] = NULL; | ||
183 | prep->payload = NULL; | ||
184 | } | ||
185 | pr_devel("<==%s() = %d\n", __func__, ret); | ||
186 | return ret; | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * dispose of the data dangling from the corpse of a asymmetric key | ||
191 | */ | ||
192 | static void asymmetric_key_destroy(struct key *key) | ||
193 | { | ||
194 | struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); | ||
195 | if (subtype) { | ||
196 | subtype->destroy(key->payload.data); | ||
197 | module_put(subtype->owner); | ||
198 | key->type_data.p[0] = NULL; | ||
199 | } | ||
200 | kfree(key->type_data.p[1]); | ||
201 | key->type_data.p[1] = NULL; | ||
202 | } | ||
203 | |||
204 | struct key_type key_type_asymmetric = { | ||
205 | .name = "asymmetric", | ||
206 | .preparse = asymmetric_key_preparse, | ||
207 | .free_preparse = asymmetric_key_free_preparse, | ||
208 | .instantiate = asymmetric_key_instantiate, | ||
209 | .match = asymmetric_key_match, | ||
210 | .destroy = asymmetric_key_destroy, | ||
211 | .describe = asymmetric_key_describe, | ||
212 | }; | ||
213 | EXPORT_SYMBOL_GPL(key_type_asymmetric); | ||
214 | |||
215 | /** | ||
216 | * register_asymmetric_key_parser - Register a asymmetric key blob parser | ||
217 | * @parser: The parser to register | ||
218 | */ | ||
219 | int register_asymmetric_key_parser(struct asymmetric_key_parser *parser) | ||
220 | { | ||
221 | struct asymmetric_key_parser *cursor; | ||
222 | int ret; | ||
223 | |||
224 | down_write(&asymmetric_key_parsers_sem); | ||
225 | |||
226 | list_for_each_entry(cursor, &asymmetric_key_parsers, link) { | ||
227 | if (strcmp(cursor->name, parser->name) == 0) { | ||
228 | pr_err("Asymmetric key parser '%s' already registered\n", | ||
229 | parser->name); | ||
230 | ret = -EEXIST; | ||
231 | goto out; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | list_add_tail(&parser->link, &asymmetric_key_parsers); | ||
236 | |||
237 | pr_notice("Asymmetric key parser '%s' registered\n", parser->name); | ||
238 | ret = 0; | ||
239 | |||
240 | out: | ||
241 | up_write(&asymmetric_key_parsers_sem); | ||
242 | return ret; | ||
243 | } | ||
244 | EXPORT_SYMBOL_GPL(register_asymmetric_key_parser); | ||
245 | |||
246 | /** | ||
247 | * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser | ||
248 | * @parser: The parser to unregister | ||
249 | */ | ||
250 | void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser) | ||
251 | { | ||
252 | down_write(&asymmetric_key_parsers_sem); | ||
253 | list_del(&parser->link); | ||
254 | up_write(&asymmetric_key_parsers_sem); | ||
255 | |||
256 | pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name); | ||
257 | } | ||
258 | EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser); | ||
259 | |||
260 | /* | ||
261 | * Module stuff | ||
262 | */ | ||
263 | static int __init asymmetric_key_init(void) | ||
264 | { | ||
265 | return register_key_type(&key_type_asymmetric); | ||
266 | } | ||
267 | |||
268 | static void __exit asymmetric_key_cleanup(void) | ||
269 | { | ||
270 | unregister_key_type(&key_type_asymmetric); | ||
271 | } | ||
272 | |||
273 | module_init(asymmetric_key_init); | ||
274 | module_exit(asymmetric_key_cleanup); | ||
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c new file mode 100644 index 000000000000..cb2e29180a87 --- /dev/null +++ b/crypto/asymmetric_keys/public_key.c | |||
@@ -0,0 +1,108 @@ | |||
1 | /* In-software asymmetric public-key crypto subtype | ||
2 | * | ||
3 | * See Documentation/crypto/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 | |||
14 | #define pr_fmt(fmt) "PKEY: "fmt | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/export.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/seq_file.h> | ||
20 | #include <keys/asymmetric-subtype.h> | ||
21 | #include "public_key.h" | ||
22 | |||
23 | MODULE_LICENSE("GPL"); | ||
24 | |||
25 | const char *const pkey_algo[PKEY_ALGO__LAST] = { | ||
26 | [PKEY_ALGO_DSA] = "DSA", | ||
27 | [PKEY_ALGO_RSA] = "RSA", | ||
28 | }; | ||
29 | EXPORT_SYMBOL_GPL(pkey_algo); | ||
30 | |||
31 | const char *const pkey_hash_algo[PKEY_HASH__LAST] = { | ||
32 | [PKEY_HASH_MD4] = "md4", | ||
33 | [PKEY_HASH_MD5] = "md5", | ||
34 | [PKEY_HASH_SHA1] = "sha1", | ||
35 | [PKEY_HASH_RIPE_MD_160] = "rmd160", | ||
36 | [PKEY_HASH_SHA256] = "sha256", | ||
37 | [PKEY_HASH_SHA384] = "sha384", | ||
38 | [PKEY_HASH_SHA512] = "sha512", | ||
39 | [PKEY_HASH_SHA224] = "sha224", | ||
40 | }; | ||
41 | EXPORT_SYMBOL_GPL(pkey_hash_algo); | ||
42 | |||
43 | const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = { | ||
44 | [PKEY_ID_PGP] = "PGP", | ||
45 | [PKEY_ID_X509] = "X509", | ||
46 | }; | ||
47 | EXPORT_SYMBOL_GPL(pkey_id_type); | ||
48 | |||
49 | /* | ||
50 | * Provide a part of a description of the key for /proc/keys. | ||
51 | */ | ||
52 | static void public_key_describe(const struct key *asymmetric_key, | ||
53 | struct seq_file *m) | ||
54 | { | ||
55 | struct public_key *key = asymmetric_key->payload.data; | ||
56 | |||
57 | if (key) | ||
58 | seq_printf(m, "%s.%s", | ||
59 | pkey_id_type[key->id_type], key->algo->name); | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * Destroy a public key algorithm key. | ||
64 | */ | ||
65 | void public_key_destroy(void *payload) | ||
66 | { | ||
67 | struct public_key *key = payload; | ||
68 | int i; | ||
69 | |||
70 | if (key) { | ||
71 | for (i = 0; i < ARRAY_SIZE(key->mpi); i++) | ||
72 | mpi_free(key->mpi[i]); | ||
73 | kfree(key); | ||
74 | } | ||
75 | } | ||
76 | EXPORT_SYMBOL_GPL(public_key_destroy); | ||
77 | |||
78 | /* | ||
79 | * Verify a signature using a public key. | ||
80 | */ | ||
81 | static int public_key_verify_signature(const struct key *key, | ||
82 | const struct public_key_signature *sig) | ||
83 | { | ||
84 | const struct public_key *pk = key->payload.data; | ||
85 | |||
86 | if (!pk->algo->verify_signature) | ||
87 | return -ENOTSUPP; | ||
88 | |||
89 | if (sig->nr_mpi != pk->algo->n_sig_mpi) { | ||
90 | pr_debug("Signature has %u MPI not %u\n", | ||
91 | sig->nr_mpi, pk->algo->n_sig_mpi); | ||
92 | return -EINVAL; | ||
93 | } | ||
94 | |||
95 | return pk->algo->verify_signature(pk, sig); | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * Public key algorithm asymmetric key subtype | ||
100 | */ | ||
101 | struct asymmetric_key_subtype public_key_subtype = { | ||
102 | .owner = THIS_MODULE, | ||
103 | .name = "public_key", | ||
104 | .describe = public_key_describe, | ||
105 | .destroy = public_key_destroy, | ||
106 | .verify_signature = public_key_verify_signature, | ||
107 | }; | ||
108 | EXPORT_SYMBOL_GPL(public_key_subtype); | ||
diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h new file mode 100644 index 000000000000..5e5e35626899 --- /dev/null +++ b/crypto/asymmetric_keys/public_key.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* Public key algorithm internals | ||
2 | * | ||
3 | * See Documentation/crypto/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 | |||
14 | #include <crypto/public_key.h> | ||
15 | |||
16 | extern struct asymmetric_key_subtype public_key_subtype; | ||
17 | |||
18 | /* | ||
19 | * Public key algorithm definition. | ||
20 | */ | ||
21 | struct public_key_algorithm { | ||
22 | const char *name; | ||
23 | u8 n_pub_mpi; /* Number of MPIs in public key */ | ||
24 | u8 n_sec_mpi; /* Number of MPIs in secret key */ | ||
25 | u8 n_sig_mpi; /* Number of MPIs in a signature */ | ||
26 | int (*verify_signature)(const struct public_key *key, | ||
27 | const struct public_key_signature *sig); | ||
28 | }; | ||
29 | |||
30 | extern const struct public_key_algorithm RSA_public_key_algorithm; | ||
diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c new file mode 100644 index 000000000000..4a6a0696f8a3 --- /dev/null +++ b/crypto/asymmetric_keys/rsa.c | |||
@@ -0,0 +1,277 @@ | |||
1 | /* RSA asymmetric public-key algorithm [RFC3447] | ||
2 | * | ||
3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #define pr_fmt(fmt) "RSA: "fmt | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include "public_key.h" | ||
17 | |||
18 | MODULE_LICENSE("GPL"); | ||
19 | MODULE_DESCRIPTION("RSA Public Key Algorithm"); | ||
20 | |||
21 | #define kenter(FMT, ...) \ | ||
22 | pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__) | ||
23 | #define kleave(FMT, ...) \ | ||
24 | pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) | ||
25 | |||
26 | /* | ||
27 | * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2]. | ||
28 | */ | ||
29 | static const u8 RSA_digest_info_MD5[] = { | ||
30 | 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, | ||
31 | 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */ | ||
32 | 0x05, 0x00, 0x04, 0x10 | ||
33 | }; | ||
34 | |||
35 | static const u8 RSA_digest_info_SHA1[] = { | ||
36 | 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, | ||
37 | 0x2B, 0x0E, 0x03, 0x02, 0x1A, | ||
38 | 0x05, 0x00, 0x04, 0x14 | ||
39 | }; | ||
40 | |||
41 | static const u8 RSA_digest_info_RIPE_MD_160[] = { | ||
42 | 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, | ||
43 | 0x2B, 0x24, 0x03, 0x02, 0x01, | ||
44 | 0x05, 0x00, 0x04, 0x14 | ||
45 | }; | ||
46 | |||
47 | static const u8 RSA_digest_info_SHA224[] = { | ||
48 | 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, | ||
49 | 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, | ||
50 | 0x05, 0x00, 0x04, 0x1C | ||
51 | }; | ||
52 | |||
53 | static const u8 RSA_digest_info_SHA256[] = { | ||
54 | 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, | ||
55 | 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, | ||
56 | 0x05, 0x00, 0x04, 0x20 | ||
57 | }; | ||
58 | |||
59 | static const u8 RSA_digest_info_SHA384[] = { | ||
60 | 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, | ||
61 | 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, | ||
62 | 0x05, 0x00, 0x04, 0x30 | ||
63 | }; | ||
64 | |||
65 | static const u8 RSA_digest_info_SHA512[] = { | ||
66 | 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, | ||
67 | 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, | ||
68 | 0x05, 0x00, 0x04, 0x40 | ||
69 | }; | ||
70 | |||
71 | static const struct { | ||
72 | const u8 *data; | ||
73 | size_t size; | ||
74 | } RSA_ASN1_templates[PKEY_HASH__LAST] = { | ||
75 | #define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) } | ||
76 | [PKEY_HASH_MD5] = _(MD5), | ||
77 | [PKEY_HASH_SHA1] = _(SHA1), | ||
78 | [PKEY_HASH_RIPE_MD_160] = _(RIPE_MD_160), | ||
79 | [PKEY_HASH_SHA256] = _(SHA256), | ||
80 | [PKEY_HASH_SHA384] = _(SHA384), | ||
81 | [PKEY_HASH_SHA512] = _(SHA512), | ||
82 | [PKEY_HASH_SHA224] = _(SHA224), | ||
83 | #undef _ | ||
84 | }; | ||
85 | |||
86 | /* | ||
87 | * RSAVP1() function [RFC3447 sec 5.2.2] | ||
88 | */ | ||
89 | static int RSAVP1(const struct public_key *key, MPI s, MPI *_m) | ||
90 | { | ||
91 | MPI m; | ||
92 | int ret; | ||
93 | |||
94 | /* (1) Validate 0 <= s < n */ | ||
95 | if (mpi_cmp_ui(s, 0) < 0) { | ||
96 | kleave(" = -EBADMSG [s < 0]"); | ||
97 | return -EBADMSG; | ||
98 | } | ||
99 | if (mpi_cmp(s, key->rsa.n) >= 0) { | ||
100 | kleave(" = -EBADMSG [s >= n]"); | ||
101 | return -EBADMSG; | ||
102 | } | ||
103 | |||
104 | m = mpi_alloc(0); | ||
105 | if (!m) | ||
106 | return -ENOMEM; | ||
107 | |||
108 | /* (2) m = s^e mod n */ | ||
109 | ret = mpi_powm(m, s, key->rsa.e, key->rsa.n); | ||
110 | if (ret < 0) { | ||
111 | mpi_free(m); | ||
112 | return ret; | ||
113 | } | ||
114 | |||
115 | *_m = m; | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * Integer to Octet String conversion [RFC3447 sec 4.1] | ||
121 | */ | ||
122 | static int RSA_I2OSP(MPI x, size_t xLen, u8 **_X) | ||
123 | { | ||
124 | unsigned X_size, x_size; | ||
125 | int X_sign; | ||
126 | u8 *X; | ||
127 | |||
128 | /* Make sure the string is the right length. The number should begin | ||
129 | * with { 0x00, 0x01, ... } so we have to account for 15 leading zero | ||
130 | * bits not being reported by MPI. | ||
131 | */ | ||
132 | x_size = mpi_get_nbits(x); | ||
133 | pr_devel("size(x)=%u xLen*8=%zu\n", x_size, xLen * 8); | ||
134 | if (x_size != xLen * 8 - 15) | ||
135 | return -ERANGE; | ||
136 | |||
137 | X = mpi_get_buffer(x, &X_size, &X_sign); | ||
138 | if (!X) | ||
139 | return -ENOMEM; | ||
140 | if (X_sign < 0) { | ||
141 | kfree(X); | ||
142 | return -EBADMSG; | ||
143 | } | ||
144 | if (X_size != xLen - 1) { | ||
145 | kfree(X); | ||
146 | return -EBADMSG; | ||
147 | } | ||
148 | |||
149 | *_X = X; | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | /* | ||
154 | * Perform the RSA signature verification. | ||
155 | * @H: Value of hash of data and metadata | ||
156 | * @EM: The computed signature value | ||
157 | * @k: The size of EM (EM[0] is an invalid location but should hold 0x00) | ||
158 | * @hash_size: The size of H | ||
159 | * @asn1_template: The DigestInfo ASN.1 template | ||
160 | * @asn1_size: Size of asm1_template[] | ||
161 | */ | ||
162 | static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size, | ||
163 | const u8 *asn1_template, size_t asn1_size) | ||
164 | { | ||
165 | unsigned PS_end, T_offset, i; | ||
166 | |||
167 | kenter(",,%zu,%zu,%zu", k, hash_size, asn1_size); | ||
168 | |||
169 | if (k < 2 + 1 + asn1_size + hash_size) | ||
170 | return -EBADMSG; | ||
171 | |||
172 | /* Decode the EMSA-PKCS1-v1_5 */ | ||
173 | if (EM[1] != 0x01) { | ||
174 | kleave(" = -EBADMSG [EM[1] == %02u]", EM[1]); | ||
175 | return -EBADMSG; | ||
176 | } | ||
177 | |||
178 | T_offset = k - (asn1_size + hash_size); | ||
179 | PS_end = T_offset - 1; | ||
180 | if (EM[PS_end] != 0x00) { | ||
181 | kleave(" = -EBADMSG [EM[T-1] == %02u]", EM[PS_end]); | ||
182 | return -EBADMSG; | ||
183 | } | ||
184 | |||
185 | for (i = 2; i < PS_end; i++) { | ||
186 | if (EM[i] != 0xff) { | ||
187 | kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]); | ||
188 | return -EBADMSG; | ||
189 | } | ||
190 | } | ||
191 | |||
192 | if (memcmp(asn1_template, EM + T_offset, asn1_size) != 0) { | ||
193 | kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]"); | ||
194 | return -EBADMSG; | ||
195 | } | ||
196 | |||
197 | if (memcmp(H, EM + T_offset + asn1_size, hash_size) != 0) { | ||
198 | kleave(" = -EKEYREJECTED [EM[T] hash mismatch]"); | ||
199 | return -EKEYREJECTED; | ||
200 | } | ||
201 | |||
202 | kleave(" = 0"); | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | /* | ||
207 | * Perform the verification step [RFC3447 sec 8.2.2]. | ||
208 | */ | ||
209 | static int RSA_verify_signature(const struct public_key *key, | ||
210 | const struct public_key_signature *sig) | ||
211 | { | ||
212 | size_t tsize; | ||
213 | int ret; | ||
214 | |||
215 | /* Variables as per RFC3447 sec 8.2.2 */ | ||
216 | const u8 *H = sig->digest; | ||
217 | u8 *EM = NULL; | ||
218 | MPI m = NULL; | ||
219 | size_t k; | ||
220 | |||
221 | kenter(""); | ||
222 | |||
223 | if (!RSA_ASN1_templates[sig->pkey_hash_algo].data) | ||
224 | return -ENOTSUPP; | ||
225 | |||
226 | /* (1) Check the signature size against the public key modulus size */ | ||
227 | k = mpi_get_nbits(key->rsa.n); | ||
228 | tsize = mpi_get_nbits(sig->rsa.s); | ||
229 | |||
230 | /* According to RFC 4880 sec 3.2, length of MPI is computed starting | ||
231 | * from most significant bit. So the RFC 3447 sec 8.2.2 size check | ||
232 | * must be relaxed to conform with shorter signatures - so we fail here | ||
233 | * only if signature length is longer than modulus size. | ||
234 | */ | ||
235 | pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize); | ||
236 | if (k < tsize) { | ||
237 | ret = -EBADMSG; | ||
238 | goto error; | ||
239 | } | ||
240 | |||
241 | /* Round up and convert to octets */ | ||
242 | k = (k + 7) / 8; | ||
243 | |||
244 | /* (2b) Apply the RSAVP1 verification primitive to the public key */ | ||
245 | ret = RSAVP1(key, sig->rsa.s, &m); | ||
246 | if (ret < 0) | ||
247 | goto error; | ||
248 | |||
249 | /* (2c) Convert the message representative (m) to an encoded message | ||
250 | * (EM) of length k octets. | ||
251 | * | ||
252 | * NOTE! The leading zero byte is suppressed by MPI, so we pass a | ||
253 | * pointer to the _preceding_ byte to RSA_verify()! | ||
254 | */ | ||
255 | ret = RSA_I2OSP(m, k, &EM); | ||
256 | if (ret < 0) | ||
257 | goto error; | ||
258 | |||
259 | ret = RSA_verify(H, EM - 1, k, sig->digest_size, | ||
260 | RSA_ASN1_templates[sig->pkey_hash_algo].data, | ||
261 | RSA_ASN1_templates[sig->pkey_hash_algo].size); | ||
262 | |||
263 | error: | ||
264 | kfree(EM); | ||
265 | mpi_free(m); | ||
266 | kleave(" = %d", ret); | ||
267 | return ret; | ||
268 | } | ||
269 | |||
270 | const struct public_key_algorithm RSA_public_key_algorithm = { | ||
271 | .name = "RSA", | ||
272 | .n_pub_mpi = 2, | ||
273 | .n_sec_mpi = 3, | ||
274 | .n_sig_mpi = 1, | ||
275 | .verify_signature = RSA_verify_signature, | ||
276 | }; | ||
277 | EXPORT_SYMBOL_GPL(RSA_public_key_algorithm); | ||
diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c new file mode 100644 index 000000000000..50b3f880b4ff --- /dev/null +++ b/crypto/asymmetric_keys/signature.c | |||
@@ -0,0 +1,49 @@ | |||
1 | /* Signature verification with an asymmetric key | ||
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 | |||
14 | #include <keys/asymmetric-subtype.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <crypto/public_key.h> | ||
18 | #include "asymmetric_keys.h" | ||
19 | |||
20 | /** | ||
21 | * verify_signature - Initiate the use of an asymmetric key to verify a signature | ||
22 | * @key: The asymmetric key to verify against | ||
23 | * @sig: The signature to check | ||
24 | * | ||
25 | * Returns 0 if successful or else an error. | ||
26 | */ | ||
27 | int verify_signature(const struct key *key, | ||
28 | const struct public_key_signature *sig) | ||
29 | { | ||
30 | const struct asymmetric_key_subtype *subtype; | ||
31 | int ret; | ||
32 | |||
33 | pr_devel("==>%s()\n", __func__); | ||
34 | |||
35 | if (key->type != &key_type_asymmetric) | ||
36 | return -EINVAL; | ||
37 | subtype = asymmetric_key_subtype(key); | ||
38 | if (!subtype || | ||
39 | !key->payload.data) | ||
40 | return -EINVAL; | ||
41 | if (!subtype->verify_signature) | ||
42 | return -ENOTSUPP; | ||
43 | |||
44 | ret = subtype->verify_signature(key, sig); | ||
45 | |||
46 | pr_devel("<==%s() = %d\n", __func__, ret); | ||
47 | return ret; | ||
48 | } | ||
49 | EXPORT_SYMBOL_GPL(verify_signature); | ||
diff --git a/crypto/asymmetric_keys/x509.asn1 b/crypto/asymmetric_keys/x509.asn1 new file mode 100644 index 000000000000..bf32b3dff088 --- /dev/null +++ b/crypto/asymmetric_keys/x509.asn1 | |||
@@ -0,0 +1,60 @@ | |||
1 | Certificate ::= SEQUENCE { | ||
2 | tbsCertificate TBSCertificate ({ x509_note_tbs_certificate }), | ||
3 | signatureAlgorithm AlgorithmIdentifier, | ||
4 | signature BIT STRING ({ x509_note_signature }) | ||
5 | } | ||
6 | |||
7 | TBSCertificate ::= SEQUENCE { | ||
8 | version [ 0 ] Version DEFAULT, | ||
9 | serialNumber CertificateSerialNumber, | ||
10 | signature AlgorithmIdentifier ({ x509_note_pkey_algo }), | ||
11 | issuer Name ({ x509_note_issuer }), | ||
12 | validity Validity, | ||
13 | subject Name ({ x509_note_subject }), | ||
14 | subjectPublicKeyInfo SubjectPublicKeyInfo, | ||
15 | issuerUniqueID [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL, | ||
16 | subjectUniqueID [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL, | ||
17 | extensions [ 3 ] Extensions OPTIONAL | ||
18 | } | ||
19 | |||
20 | Version ::= INTEGER | ||
21 | CertificateSerialNumber ::= INTEGER | ||
22 | |||
23 | AlgorithmIdentifier ::= SEQUENCE { | ||
24 | algorithm OBJECT IDENTIFIER ({ x509_note_OID }), | ||
25 | parameters ANY OPTIONAL | ||
26 | } | ||
27 | |||
28 | Name ::= SEQUENCE OF RelativeDistinguishedName | ||
29 | |||
30 | RelativeDistinguishedName ::= SET OF AttributeValueAssertion | ||
31 | |||
32 | AttributeValueAssertion ::= SEQUENCE { | ||
33 | attributeType OBJECT IDENTIFIER ({ x509_note_OID }), | ||
34 | attributeValue ANY ({ x509_extract_name_segment }) | ||
35 | } | ||
36 | |||
37 | Validity ::= SEQUENCE { | ||
38 | notBefore Time ({ x509_note_not_before }), | ||
39 | notAfter Time ({ x509_note_not_after }) | ||
40 | } | ||
41 | |||
42 | Time ::= CHOICE { | ||
43 | utcTime UTCTime, | ||
44 | generalTime GeneralizedTime | ||
45 | } | ||
46 | |||
47 | SubjectPublicKeyInfo ::= SEQUENCE { | ||
48 | algorithm AlgorithmIdentifier, | ||
49 | subjectPublicKey BIT STRING ({ x509_extract_key_data }) | ||
50 | } | ||
51 | |||
52 | UniqueIdentifier ::= BIT STRING | ||
53 | |||
54 | Extensions ::= SEQUENCE OF Extension | ||
55 | |||
56 | Extension ::= SEQUENCE { | ||
57 | extnid OBJECT IDENTIFIER ({ x509_note_OID }), | ||
58 | critical BOOLEAN DEFAULT, | ||
59 | extnValue OCTET STRING ({ x509_process_extension }) | ||
60 | } | ||
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c new file mode 100644 index 000000000000..7fabc4c01993 --- /dev/null +++ b/crypto/asymmetric_keys/x509_cert_parser.c | |||
@@ -0,0 +1,496 @@ | |||
1 | /* X.509 certificate parser | ||
2 | * | ||
3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #define pr_fmt(fmt) "X.509: "fmt | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/oid_registry.h> | ||
17 | #include "public_key.h" | ||
18 | #include "x509_parser.h" | ||
19 | #include "x509-asn1.h" | ||
20 | #include "x509_rsakey-asn1.h" | ||
21 | |||
22 | struct x509_parse_context { | ||
23 | struct x509_certificate *cert; /* Certificate being constructed */ | ||
24 | unsigned long data; /* Start of data */ | ||
25 | const void *cert_start; /* Start of cert content */ | ||
26 | const void *key; /* Key data */ | ||
27 | size_t key_size; /* Size of key data */ | ||
28 | enum OID last_oid; /* Last OID encountered */ | ||
29 | enum OID algo_oid; /* Algorithm OID */ | ||
30 | unsigned char nr_mpi; /* Number of MPIs stored */ | ||
31 | u8 o_size; /* Size of organizationName (O) */ | ||
32 | u8 cn_size; /* Size of commonName (CN) */ | ||
33 | u8 email_size; /* Size of emailAddress */ | ||
34 | u16 o_offset; /* Offset of organizationName (O) */ | ||
35 | u16 cn_offset; /* Offset of commonName (CN) */ | ||
36 | u16 email_offset; /* Offset of emailAddress */ | ||
37 | }; | ||
38 | |||
39 | /* | ||
40 | * Free an X.509 certificate | ||
41 | */ | ||
42 | void x509_free_certificate(struct x509_certificate *cert) | ||
43 | { | ||
44 | if (cert) { | ||
45 | public_key_destroy(cert->pub); | ||
46 | kfree(cert->issuer); | ||
47 | kfree(cert->subject); | ||
48 | kfree(cert->fingerprint); | ||
49 | kfree(cert->authority); | ||
50 | kfree(cert); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * Parse an X.509 certificate | ||
56 | */ | ||
57 | struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) | ||
58 | { | ||
59 | struct x509_certificate *cert; | ||
60 | struct x509_parse_context *ctx; | ||
61 | long ret; | ||
62 | |||
63 | ret = -ENOMEM; | ||
64 | cert = kzalloc(sizeof(struct x509_certificate), GFP_KERNEL); | ||
65 | if (!cert) | ||
66 | goto error_no_cert; | ||
67 | cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL); | ||
68 | if (!cert->pub) | ||
69 | goto error_no_ctx; | ||
70 | ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL); | ||
71 | if (!ctx) | ||
72 | goto error_no_ctx; | ||
73 | |||
74 | ctx->cert = cert; | ||
75 | ctx->data = (unsigned long)data; | ||
76 | |||
77 | /* Attempt to decode the certificate */ | ||
78 | ret = asn1_ber_decoder(&x509_decoder, ctx, data, datalen); | ||
79 | if (ret < 0) | ||
80 | goto error_decode; | ||
81 | |||
82 | /* Decode the public key */ | ||
83 | ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx, | ||
84 | ctx->key, ctx->key_size); | ||
85 | if (ret < 0) | ||
86 | goto error_decode; | ||
87 | |||
88 | kfree(ctx); | ||
89 | return cert; | ||
90 | |||
91 | error_decode: | ||
92 | kfree(ctx); | ||
93 | error_no_ctx: | ||
94 | x509_free_certificate(cert); | ||
95 | error_no_cert: | ||
96 | return ERR_PTR(ret); | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * Note an OID when we find one for later processing when we know how | ||
101 | * to interpret it. | ||
102 | */ | ||
103 | int x509_note_OID(void *context, size_t hdrlen, | ||
104 | unsigned char tag, | ||
105 | const void *value, size_t vlen) | ||
106 | { | ||
107 | struct x509_parse_context *ctx = context; | ||
108 | |||
109 | ctx->last_oid = look_up_OID(value, vlen); | ||
110 | if (ctx->last_oid == OID__NR) { | ||
111 | char buffer[50]; | ||
112 | sprint_oid(value, vlen, buffer, sizeof(buffer)); | ||
113 | pr_debug("Unknown OID: [%lu] %s\n", | ||
114 | (unsigned long)value - ctx->data, buffer); | ||
115 | } | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * Save the position of the TBS data so that we can check the signature over it | ||
121 | * later. | ||
122 | */ | ||
123 | int x509_note_tbs_certificate(void *context, size_t hdrlen, | ||
124 | unsigned char tag, | ||
125 | const void *value, size_t vlen) | ||
126 | { | ||
127 | struct x509_parse_context *ctx = context; | ||
128 | |||
129 | pr_debug("x509_note_tbs_certificate(,%zu,%02x,%ld,%zu)!\n", | ||
130 | hdrlen, tag, (unsigned long)value - ctx->data, vlen); | ||
131 | |||
132 | ctx->cert->tbs = value - hdrlen; | ||
133 | ctx->cert->tbs_size = vlen + hdrlen; | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | /* | ||
138 | * Record the public key algorithm | ||
139 | */ | ||
140 | int x509_note_pkey_algo(void *context, size_t hdrlen, | ||
141 | unsigned char tag, | ||
142 | const void *value, size_t vlen) | ||
143 | { | ||
144 | struct x509_parse_context *ctx = context; | ||
145 | |||
146 | pr_debug("PubKey Algo: %u\n", ctx->last_oid); | ||
147 | |||
148 | switch (ctx->last_oid) { | ||
149 | case OID_md2WithRSAEncryption: | ||
150 | case OID_md3WithRSAEncryption: | ||
151 | default: | ||
152 | return -ENOPKG; /* Unsupported combination */ | ||
153 | |||
154 | case OID_md4WithRSAEncryption: | ||
155 | ctx->cert->sig_hash_algo = PKEY_HASH_MD5; | ||
156 | ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; | ||
157 | break; | ||
158 | |||
159 | case OID_sha1WithRSAEncryption: | ||
160 | ctx->cert->sig_hash_algo = PKEY_HASH_SHA1; | ||
161 | ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; | ||
162 | break; | ||
163 | |||
164 | case OID_sha256WithRSAEncryption: | ||
165 | ctx->cert->sig_hash_algo = PKEY_HASH_SHA256; | ||
166 | ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; | ||
167 | break; | ||
168 | |||
169 | case OID_sha384WithRSAEncryption: | ||
170 | ctx->cert->sig_hash_algo = PKEY_HASH_SHA384; | ||
171 | ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; | ||
172 | break; | ||
173 | |||
174 | case OID_sha512WithRSAEncryption: | ||
175 | ctx->cert->sig_hash_algo = PKEY_HASH_SHA512; | ||
176 | ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; | ||
177 | break; | ||
178 | |||
179 | case OID_sha224WithRSAEncryption: | ||
180 | ctx->cert->sig_hash_algo = PKEY_HASH_SHA224; | ||
181 | ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA; | ||
182 | break; | ||
183 | } | ||
184 | |||
185 | ctx->algo_oid = ctx->last_oid; | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * Note the whereabouts and type of the signature. | ||
191 | */ | ||
192 | int x509_note_signature(void *context, size_t hdrlen, | ||
193 | unsigned char tag, | ||
194 | const void *value, size_t vlen) | ||
195 | { | ||
196 | struct x509_parse_context *ctx = context; | ||
197 | |||
198 | pr_debug("Signature type: %u size %zu\n", ctx->last_oid, vlen); | ||
199 | |||
200 | if (ctx->last_oid != ctx->algo_oid) { | ||
201 | pr_warn("Got cert with pkey (%u) and sig (%u) algorithm OIDs\n", | ||
202 | ctx->algo_oid, ctx->last_oid); | ||
203 | return -EINVAL; | ||
204 | } | ||
205 | |||
206 | ctx->cert->sig = value; | ||
207 | ctx->cert->sig_size = vlen; | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * Note some of the name segments from which we'll fabricate a name. | ||
213 | */ | ||
214 | int x509_extract_name_segment(void *context, size_t hdrlen, | ||
215 | unsigned char tag, | ||
216 | const void *value, size_t vlen) | ||
217 | { | ||
218 | struct x509_parse_context *ctx = context; | ||
219 | |||
220 | switch (ctx->last_oid) { | ||
221 | case OID_commonName: | ||
222 | ctx->cn_size = vlen; | ||
223 | ctx->cn_offset = (unsigned long)value - ctx->data; | ||
224 | break; | ||
225 | case OID_organizationName: | ||
226 | ctx->o_size = vlen; | ||
227 | ctx->o_offset = (unsigned long)value - ctx->data; | ||
228 | break; | ||
229 | case OID_email_address: | ||
230 | ctx->email_size = vlen; | ||
231 | ctx->email_offset = (unsigned long)value - ctx->data; | ||
232 | break; | ||
233 | default: | ||
234 | break; | ||
235 | } | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | /* | ||
241 | * Fabricate and save the issuer and subject names | ||
242 | */ | ||
243 | static int x509_fabricate_name(struct x509_parse_context *ctx, size_t hdrlen, | ||
244 | unsigned char tag, | ||
245 | char **_name, size_t vlen) | ||
246 | { | ||
247 | const void *name, *data = (const void *)ctx->data; | ||
248 | size_t namesize; | ||
249 | char *buffer; | ||
250 | |||
251 | if (*_name) | ||
252 | return -EINVAL; | ||
253 | |||
254 | /* Empty name string if no material */ | ||
255 | if (!ctx->cn_size && !ctx->o_size && !ctx->email_size) { | ||
256 | buffer = kmalloc(1, GFP_KERNEL); | ||
257 | if (!buffer) | ||
258 | return -ENOMEM; | ||
259 | buffer[0] = 0; | ||
260 | goto done; | ||
261 | } | ||
262 | |||
263 | if (ctx->cn_size && ctx->o_size) { | ||
264 | /* Consider combining O and CN, but use only the CN if it is | ||
265 | * prefixed by the O, or a significant portion thereof. | ||
266 | */ | ||
267 | namesize = ctx->cn_size; | ||
268 | name = data + ctx->cn_offset; | ||
269 | if (ctx->cn_size >= ctx->o_size && | ||
270 | memcmp(data + ctx->cn_offset, data + ctx->o_offset, | ||
271 | ctx->o_size) == 0) | ||
272 | goto single_component; | ||
273 | if (ctx->cn_size >= 7 && | ||
274 | ctx->o_size >= 7 && | ||
275 | memcmp(data + ctx->cn_offset, data + ctx->o_offset, 7) == 0) | ||
276 | goto single_component; | ||
277 | |||
278 | buffer = kmalloc(ctx->o_size + 2 + ctx->cn_size + 1, | ||
279 | GFP_KERNEL); | ||
280 | if (!buffer) | ||
281 | return -ENOMEM; | ||
282 | |||
283 | memcpy(buffer, | ||
284 | data + ctx->o_offset, ctx->o_size); | ||
285 | buffer[ctx->o_size + 0] = ':'; | ||
286 | buffer[ctx->o_size + 1] = ' '; | ||
287 | memcpy(buffer + ctx->o_size + 2, | ||
288 | data + ctx->cn_offset, ctx->cn_size); | ||
289 | buffer[ctx->o_size + 2 + ctx->cn_size] = 0; | ||
290 | goto done; | ||
291 | |||
292 | } else if (ctx->cn_size) { | ||
293 | namesize = ctx->cn_size; | ||
294 | name = data + ctx->cn_offset; | ||
295 | } else if (ctx->o_size) { | ||
296 | namesize = ctx->o_size; | ||
297 | name = data + ctx->o_offset; | ||
298 | } else { | ||
299 | namesize = ctx->email_size; | ||
300 | name = data + ctx->email_offset; | ||
301 | } | ||
302 | |||
303 | single_component: | ||
304 | buffer = kmalloc(namesize + 1, GFP_KERNEL); | ||
305 | if (!buffer) | ||
306 | return -ENOMEM; | ||
307 | memcpy(buffer, name, namesize); | ||
308 | buffer[namesize] = 0; | ||
309 | |||
310 | done: | ||
311 | *_name = buffer; | ||
312 | ctx->cn_size = 0; | ||
313 | ctx->o_size = 0; | ||
314 | ctx->email_size = 0; | ||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | int x509_note_issuer(void *context, size_t hdrlen, | ||
319 | unsigned char tag, | ||
320 | const void *value, size_t vlen) | ||
321 | { | ||
322 | struct x509_parse_context *ctx = context; | ||
323 | return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->issuer, vlen); | ||
324 | } | ||
325 | |||
326 | int x509_note_subject(void *context, size_t hdrlen, | ||
327 | unsigned char tag, | ||
328 | const void *value, size_t vlen) | ||
329 | { | ||
330 | struct x509_parse_context *ctx = context; | ||
331 | return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->subject, vlen); | ||
332 | } | ||
333 | |||
334 | /* | ||
335 | * Extract the data for the public key algorithm | ||
336 | */ | ||
337 | int x509_extract_key_data(void *context, size_t hdrlen, | ||
338 | unsigned char tag, | ||
339 | const void *value, size_t vlen) | ||
340 | { | ||
341 | struct x509_parse_context *ctx = context; | ||
342 | |||
343 | if (ctx->last_oid != OID_rsaEncryption) | ||
344 | return -ENOPKG; | ||
345 | |||
346 | /* There seems to be an extraneous 0 byte on the front of the data */ | ||
347 | ctx->cert->pkey_algo = PKEY_ALGO_RSA; | ||
348 | ctx->key = value + 1; | ||
349 | ctx->key_size = vlen - 1; | ||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | /* | ||
354 | * Extract a RSA public key value | ||
355 | */ | ||
356 | int rsa_extract_mpi(void *context, size_t hdrlen, | ||
357 | unsigned char tag, | ||
358 | const void *value, size_t vlen) | ||
359 | { | ||
360 | struct x509_parse_context *ctx = context; | ||
361 | MPI mpi; | ||
362 | |||
363 | if (ctx->nr_mpi >= ARRAY_SIZE(ctx->cert->pub->mpi)) { | ||
364 | pr_err("Too many public key MPIs in certificate\n"); | ||
365 | return -EBADMSG; | ||
366 | } | ||
367 | |||
368 | mpi = mpi_read_raw_data(value, vlen); | ||
369 | if (!mpi) | ||
370 | return -ENOMEM; | ||
371 | |||
372 | ctx->cert->pub->mpi[ctx->nr_mpi++] = mpi; | ||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | /* | ||
377 | * Process certificate extensions that are used to qualify the certificate. | ||
378 | */ | ||
379 | int x509_process_extension(void *context, size_t hdrlen, | ||
380 | unsigned char tag, | ||
381 | const void *value, size_t vlen) | ||
382 | { | ||
383 | struct x509_parse_context *ctx = context; | ||
384 | const unsigned char *v = value; | ||
385 | char *f; | ||
386 | int i; | ||
387 | |||
388 | pr_debug("Extension: %u\n", ctx->last_oid); | ||
389 | |||
390 | if (ctx->last_oid == OID_subjectKeyIdentifier) { | ||
391 | /* Get hold of the key fingerprint */ | ||
392 | if (vlen < 3) | ||
393 | return -EBADMSG; | ||
394 | if (v[0] != ASN1_OTS || v[1] != vlen - 2) | ||
395 | return -EBADMSG; | ||
396 | v += 2; | ||
397 | vlen -= 2; | ||
398 | |||
399 | f = kmalloc(vlen * 2 + 1, GFP_KERNEL); | ||
400 | if (!f) | ||
401 | return -ENOMEM; | ||
402 | for (i = 0; i < vlen; i++) | ||
403 | sprintf(f + i * 2, "%02x", v[i]); | ||
404 | pr_debug("fingerprint %s\n", f); | ||
405 | ctx->cert->fingerprint = f; | ||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | if (ctx->last_oid == OID_authorityKeyIdentifier) { | ||
410 | /* Get hold of the CA key fingerprint */ | ||
411 | if (vlen < 5) | ||
412 | return -EBADMSG; | ||
413 | if (v[0] != (ASN1_SEQ | (ASN1_CONS << 5)) || | ||
414 | v[1] != vlen - 2 || | ||
415 | v[2] != (ASN1_CONT << 6) || | ||
416 | v[3] != vlen - 4) | ||
417 | return -EBADMSG; | ||
418 | v += 4; | ||
419 | vlen -= 4; | ||
420 | |||
421 | f = kmalloc(vlen * 2 + 1, GFP_KERNEL); | ||
422 | if (!f) | ||
423 | return -ENOMEM; | ||
424 | for (i = 0; i < vlen; i++) | ||
425 | sprintf(f + i * 2, "%02x", v[i]); | ||
426 | pr_debug("authority %s\n", f); | ||
427 | ctx->cert->authority = f; | ||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | /* | ||
435 | * Record a certificate time. | ||
436 | */ | ||
437 | static int x509_note_time(struct tm *tm, size_t hdrlen, | ||
438 | unsigned char tag, | ||
439 | const unsigned char *value, size_t vlen) | ||
440 | { | ||
441 | const unsigned char *p = value; | ||
442 | |||
443 | #define dec2bin(X) ((X) - '0') | ||
444 | #define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; x; }) | ||
445 | |||
446 | if (tag == ASN1_UNITIM) { | ||
447 | /* UTCTime: YYMMDDHHMMSSZ */ | ||
448 | if (vlen != 13) | ||
449 | goto unsupported_time; | ||
450 | tm->tm_year = DD2bin(p); | ||
451 | if (tm->tm_year >= 50) | ||
452 | tm->tm_year += 1900; | ||
453 | else | ||
454 | tm->tm_year += 2000; | ||
455 | } else if (tag == ASN1_GENTIM) { | ||
456 | /* GenTime: YYYYMMDDHHMMSSZ */ | ||
457 | if (vlen != 15) | ||
458 | goto unsupported_time; | ||
459 | tm->tm_year = DD2bin(p) * 100 + DD2bin(p); | ||
460 | } else { | ||
461 | goto unsupported_time; | ||
462 | } | ||
463 | |||
464 | tm->tm_year -= 1900; | ||
465 | tm->tm_mon = DD2bin(p) - 1; | ||
466 | tm->tm_mday = DD2bin(p); | ||
467 | tm->tm_hour = DD2bin(p); | ||
468 | tm->tm_min = DD2bin(p); | ||
469 | tm->tm_sec = DD2bin(p); | ||
470 | |||
471 | if (*p != 'Z') | ||
472 | goto unsupported_time; | ||
473 | |||
474 | return 0; | ||
475 | |||
476 | unsupported_time: | ||
477 | pr_debug("Got unsupported time [tag %02x]: '%*.*s'\n", | ||
478 | tag, (int)vlen, (int)vlen, value); | ||
479 | return -EBADMSG; | ||
480 | } | ||
481 | |||
482 | int x509_note_not_before(void *context, size_t hdrlen, | ||
483 | unsigned char tag, | ||
484 | const void *value, size_t vlen) | ||
485 | { | ||
486 | struct x509_parse_context *ctx = context; | ||
487 | return x509_note_time(&ctx->cert->valid_from, hdrlen, tag, value, vlen); | ||
488 | } | ||
489 | |||
490 | int x509_note_not_after(void *context, size_t hdrlen, | ||
491 | unsigned char tag, | ||
492 | const void *value, size_t vlen) | ||
493 | { | ||
494 | struct x509_parse_context *ctx = context; | ||
495 | return x509_note_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen); | ||
496 | } | ||
diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h new file mode 100644 index 000000000000..f86dc5fcc4ad --- /dev/null +++ b/crypto/asymmetric_keys/x509_parser.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* X.509 certificate parser internal definitions | ||
2 | * | ||
3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <crypto/public_key.h> | ||
13 | |||
14 | struct x509_certificate { | ||
15 | struct x509_certificate *next; | ||
16 | struct public_key *pub; /* Public key details */ | ||
17 | char *issuer; /* Name of certificate issuer */ | ||
18 | char *subject; /* Name of certificate subject */ | ||
19 | char *fingerprint; /* Key fingerprint as hex */ | ||
20 | char *authority; /* Authority key fingerprint as hex */ | ||
21 | struct tm valid_from; | ||
22 | struct tm valid_to; | ||
23 | enum pkey_algo pkey_algo : 8; /* Public key algorithm */ | ||
24 | enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ | ||
25 | enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ | ||
26 | const void *tbs; /* Signed data */ | ||
27 | size_t tbs_size; /* Size of signed data */ | ||
28 | const void *sig; /* Signature data */ | ||
29 | size_t sig_size; /* Size of sigature */ | ||
30 | }; | ||
31 | |||
32 | /* | ||
33 | * x509_cert_parser.c | ||
34 | */ | ||
35 | extern void x509_free_certificate(struct x509_certificate *cert); | ||
36 | extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen); | ||
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c new file mode 100644 index 000000000000..06007f0e880c --- /dev/null +++ b/crypto/asymmetric_keys/x509_public_key.c | |||
@@ -0,0 +1,239 @@ | |||
1 | /* Instantiate a public key crypto key from an X.509 Certificate | ||
2 | * | ||
3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #define pr_fmt(fmt) "X.509: "fmt | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/mpi.h> | ||
18 | #include <linux/asn1_decoder.h> | ||
19 | #include <keys/asymmetric-subtype.h> | ||
20 | #include <keys/asymmetric-parser.h> | ||
21 | #include <crypto/hash.h> | ||
22 | #include "asymmetric_keys.h" | ||
23 | #include "public_key.h" | ||
24 | #include "x509_parser.h" | ||
25 | |||
26 | static const | ||
27 | struct public_key_algorithm *x509_public_key_algorithms[PKEY_ALGO__LAST] = { | ||
28 | [PKEY_ALGO_DSA] = NULL, | ||
29 | #if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ | ||
30 | defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) | ||
31 | [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, | ||
32 | #endif | ||
33 | }; | ||
34 | |||
35 | /* | ||
36 | * Check the signature on a certificate using the provided public key | ||
37 | */ | ||
38 | static int x509_check_signature(const struct public_key *pub, | ||
39 | const struct x509_certificate *cert) | ||
40 | { | ||
41 | struct public_key_signature *sig; | ||
42 | struct crypto_shash *tfm; | ||
43 | struct shash_desc *desc; | ||
44 | size_t digest_size, desc_size; | ||
45 | int ret; | ||
46 | |||
47 | pr_devel("==>%s()\n", __func__); | ||
48 | |||
49 | /* Allocate the hashing algorithm we're going to need and find out how | ||
50 | * big the hash operational data will be. | ||
51 | */ | ||
52 | tfm = crypto_alloc_shash(pkey_hash_algo[cert->sig_hash_algo], 0, 0); | ||
53 | if (IS_ERR(tfm)) | ||
54 | return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); | ||
55 | |||
56 | desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); | ||
57 | digest_size = crypto_shash_digestsize(tfm); | ||
58 | |||
59 | /* We allocate the hash operational data storage on the end of our | ||
60 | * context data. | ||
61 | */ | ||
62 | ret = -ENOMEM; | ||
63 | sig = kzalloc(sizeof(*sig) + desc_size + digest_size, GFP_KERNEL); | ||
64 | if (!sig) | ||
65 | goto error_no_sig; | ||
66 | |||
67 | sig->pkey_hash_algo = cert->sig_hash_algo; | ||
68 | sig->digest = (u8 *)sig + sizeof(*sig) + desc_size; | ||
69 | sig->digest_size = digest_size; | ||
70 | |||
71 | desc = (void *)sig + sizeof(*sig); | ||
72 | desc->tfm = tfm; | ||
73 | desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; | ||
74 | |||
75 | ret = crypto_shash_init(desc); | ||
76 | if (ret < 0) | ||
77 | goto error; | ||
78 | |||
79 | ret = -ENOMEM; | ||
80 | sig->rsa.s = mpi_read_raw_data(cert->sig, cert->sig_size); | ||
81 | if (!sig->rsa.s) | ||
82 | goto error; | ||
83 | |||
84 | ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); | ||
85 | if (ret < 0) | ||
86 | goto error_mpi; | ||
87 | |||
88 | ret = pub->algo->verify_signature(pub, sig); | ||
89 | |||
90 | pr_debug("Cert Verification: %d\n", ret); | ||
91 | |||
92 | error_mpi: | ||
93 | mpi_free(sig->rsa.s); | ||
94 | error: | ||
95 | kfree(sig); | ||
96 | error_no_sig: | ||
97 | crypto_free_shash(tfm); | ||
98 | |||
99 | pr_devel("<==%s() = %d\n", __func__, ret); | ||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | /* | ||
104 | * Attempt to parse a data blob for a key as an X509 certificate. | ||
105 | */ | ||
106 | static int x509_key_preparse(struct key_preparsed_payload *prep) | ||
107 | { | ||
108 | struct x509_certificate *cert; | ||
109 | struct tm now; | ||
110 | size_t srlen, sulen; | ||
111 | char *desc = NULL; | ||
112 | int ret; | ||
113 | |||
114 | cert = x509_cert_parse(prep->data, prep->datalen); | ||
115 | if (IS_ERR(cert)) | ||
116 | return PTR_ERR(cert); | ||
117 | |||
118 | pr_devel("Cert Issuer: %s\n", cert->issuer); | ||
119 | pr_devel("Cert Subject: %s\n", cert->subject); | ||
120 | pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); | ||
121 | pr_devel("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", | ||
122 | cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, | ||
123 | cert->valid_from.tm_mday, cert->valid_from.tm_hour, | ||
124 | cert->valid_from.tm_min, cert->valid_from.tm_sec); | ||
125 | pr_devel("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n", | ||
126 | cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1, | ||
127 | cert->valid_to.tm_mday, cert->valid_to.tm_hour, | ||
128 | cert->valid_to.tm_min, cert->valid_to.tm_sec); | ||
129 | pr_devel("Cert Signature: %s + %s\n", | ||
130 | pkey_algo[cert->sig_pkey_algo], | ||
131 | pkey_hash_algo[cert->sig_hash_algo]); | ||
132 | |||
133 | if (!cert->fingerprint || !cert->authority) { | ||
134 | pr_warn("Cert for '%s' must have SubjKeyId and AuthKeyId extensions\n", | ||
135 | cert->subject); | ||
136 | ret = -EKEYREJECTED; | ||
137 | goto error_free_cert; | ||
138 | } | ||
139 | |||
140 | time_to_tm(CURRENT_TIME.tv_sec, 0, &now); | ||
141 | pr_devel("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", | ||
142 | now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, | ||
143 | now.tm_hour, now.tm_min, now.tm_sec); | ||
144 | if (now.tm_year < cert->valid_from.tm_year || | ||
145 | (now.tm_year == cert->valid_from.tm_year && | ||
146 | (now.tm_mon < cert->valid_from.tm_mon || | ||
147 | (now.tm_mon == cert->valid_from.tm_mon && | ||
148 | (now.tm_mday < cert->valid_from.tm_mday || | ||
149 | (now.tm_mday == cert->valid_from.tm_mday && | ||
150 | (now.tm_hour < cert->valid_from.tm_hour || | ||
151 | (now.tm_hour == cert->valid_from.tm_hour && | ||
152 | (now.tm_min < cert->valid_from.tm_min || | ||
153 | (now.tm_min == cert->valid_from.tm_min && | ||
154 | (now.tm_sec < cert->valid_from.tm_sec | ||
155 | ))))))))))) { | ||
156 | pr_warn("Cert %s is not yet valid\n", cert->fingerprint); | ||
157 | ret = -EKEYREJECTED; | ||
158 | goto error_free_cert; | ||
159 | } | ||
160 | if (now.tm_year > cert->valid_to.tm_year || | ||
161 | (now.tm_year == cert->valid_to.tm_year && | ||
162 | (now.tm_mon > cert->valid_to.tm_mon || | ||
163 | (now.tm_mon == cert->valid_to.tm_mon && | ||
164 | (now.tm_mday > cert->valid_to.tm_mday || | ||
165 | (now.tm_mday == cert->valid_to.tm_mday && | ||
166 | (now.tm_hour > cert->valid_to.tm_hour || | ||
167 | (now.tm_hour == cert->valid_to.tm_hour && | ||
168 | (now.tm_min > cert->valid_to.tm_min || | ||
169 | (now.tm_min == cert->valid_to.tm_min && | ||
170 | (now.tm_sec > cert->valid_to.tm_sec | ||
171 | ))))))))))) { | ||
172 | pr_warn("Cert %s has expired\n", cert->fingerprint); | ||
173 | ret = -EKEYEXPIRED; | ||
174 | goto error_free_cert; | ||
175 | } | ||
176 | |||
177 | cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo]; | ||
178 | cert->pub->id_type = PKEY_ID_X509; | ||
179 | |||
180 | /* Check the signature on the key */ | ||
181 | if (strcmp(cert->fingerprint, cert->authority) == 0) { | ||
182 | ret = x509_check_signature(cert->pub, cert); | ||
183 | if (ret < 0) | ||
184 | goto error_free_cert; | ||
185 | } | ||
186 | |||
187 | /* Propose a description */ | ||
188 | sulen = strlen(cert->subject); | ||
189 | srlen = strlen(cert->fingerprint); | ||
190 | ret = -ENOMEM; | ||
191 | desc = kmalloc(sulen + 2 + srlen + 1, GFP_KERNEL); | ||
192 | if (!desc) | ||
193 | goto error_free_cert; | ||
194 | memcpy(desc, cert->subject, sulen); | ||
195 | desc[sulen] = ':'; | ||
196 | desc[sulen + 1] = ' '; | ||
197 | memcpy(desc + sulen + 2, cert->fingerprint, srlen); | ||
198 | desc[sulen + 2 + srlen] = 0; | ||
199 | |||
200 | /* We're pinning the module by being linked against it */ | ||
201 | __module_get(public_key_subtype.owner); | ||
202 | prep->type_data[0] = &public_key_subtype; | ||
203 | prep->type_data[1] = cert->fingerprint; | ||
204 | prep->payload = cert->pub; | ||
205 | prep->description = desc; | ||
206 | prep->quotalen = 100; | ||
207 | |||
208 | /* We've finished with the certificate */ | ||
209 | cert->pub = NULL; | ||
210 | cert->fingerprint = NULL; | ||
211 | desc = NULL; | ||
212 | ret = 0; | ||
213 | |||
214 | error_free_cert: | ||
215 | x509_free_certificate(cert); | ||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | static struct asymmetric_key_parser x509_key_parser = { | ||
220 | .owner = THIS_MODULE, | ||
221 | .name = "x509", | ||
222 | .parse = x509_key_preparse, | ||
223 | }; | ||
224 | |||
225 | /* | ||
226 | * Module stuff | ||
227 | */ | ||
228 | static int __init x509_key_init(void) | ||
229 | { | ||
230 | return register_asymmetric_key_parser(&x509_key_parser); | ||
231 | } | ||
232 | |||
233 | static void __exit x509_key_exit(void) | ||
234 | { | ||
235 | unregister_asymmetric_key_parser(&x509_key_parser); | ||
236 | } | ||
237 | |||
238 | module_init(x509_key_init); | ||
239 | module_exit(x509_key_exit); | ||
diff --git a/crypto/asymmetric_keys/x509_rsakey.asn1 b/crypto/asymmetric_keys/x509_rsakey.asn1 new file mode 100644 index 000000000000..4ec7cc6532c1 --- /dev/null +++ b/crypto/asymmetric_keys/x509_rsakey.asn1 | |||
@@ -0,0 +1,4 @@ | |||
1 | RSAPublicKey ::= SEQUENCE { | ||
2 | modulus INTEGER ({ rsa_extract_mpi }), -- n | ||
3 | publicExponent INTEGER ({ rsa_extract_mpi }) -- e | ||
4 | } | ||
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index e622863b292f..086f381d6489 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c | |||
@@ -31,18 +31,18 @@ | |||
31 | 31 | ||
32 | /* create a new cifs key */ | 32 | /* create a new cifs key */ |
33 | static int | 33 | static int |
34 | cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen) | 34 | cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep) |
35 | { | 35 | { |
36 | char *payload; | 36 | char *payload; |
37 | int ret; | 37 | int ret; |
38 | 38 | ||
39 | ret = -ENOMEM; | 39 | ret = -ENOMEM; |
40 | payload = kmalloc(datalen, GFP_KERNEL); | 40 | payload = kmalloc(prep->datalen, GFP_KERNEL); |
41 | if (!payload) | 41 | if (!payload) |
42 | goto error; | 42 | goto error; |
43 | 43 | ||
44 | /* attach the data */ | 44 | /* attach the data */ |
45 | memcpy(payload, data, datalen); | 45 | memcpy(payload, prep->data, prep->datalen); |
46 | key->payload.data = payload; | 46 | key->payload.data = payload; |
47 | ret = 0; | 47 | ret = 0; |
48 | 48 | ||
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 2ee5c54797fa..fc783e264420 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -167,17 +167,17 @@ static struct shrinker cifs_shrinker = { | |||
167 | }; | 167 | }; |
168 | 168 | ||
169 | static int | 169 | static int |
170 | cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen) | 170 | cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) |
171 | { | 171 | { |
172 | char *payload; | 172 | char *payload; |
173 | 173 | ||
174 | payload = kmalloc(datalen, GFP_KERNEL); | 174 | payload = kmalloc(prep->datalen, GFP_KERNEL); |
175 | if (!payload) | 175 | if (!payload) |
176 | return -ENOMEM; | 176 | return -ENOMEM; |
177 | 177 | ||
178 | memcpy(payload, data, datalen); | 178 | memcpy(payload, prep->data, prep->datalen); |
179 | key->payload.data = payload; | 179 | key->payload.data = payload; |
180 | key->datalen = datalen; | 180 | key->datalen = prep->datalen; |
181 | return 0; | 181 | return 0; |
182 | } | 182 | } |
183 | 183 | ||
diff --git a/include/asm-generic/bitops/count_zeros.h b/include/asm-generic/bitops/count_zeros.h new file mode 100644 index 000000000000..97520d21fe62 --- /dev/null +++ b/include/asm-generic/bitops/count_zeros.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /* Count leading and trailing zeros functions | ||
2 | * | ||
3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ | ||
13 | #define _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ | ||
14 | |||
15 | #include <asm/bitops.h> | ||
16 | |||
17 | /** | ||
18 | * count_leading_zeros - Count the number of zeros from the MSB back | ||
19 | * @x: The value | ||
20 | * | ||
21 | * Count the number of leading zeros from the MSB going towards the LSB in @x. | ||
22 | * | ||
23 | * If the MSB of @x is set, the result is 0. | ||
24 | * If only the LSB of @x is set, then the result is BITS_PER_LONG-1. | ||
25 | * If @x is 0 then the result is COUNT_LEADING_ZEROS_0. | ||
26 | */ | ||
27 | static inline int count_leading_zeros(unsigned long x) | ||
28 | { | ||
29 | if (sizeof(x) == 4) | ||
30 | return BITS_PER_LONG - fls(x); | ||
31 | else | ||
32 | return BITS_PER_LONG - fls64(x); | ||
33 | } | ||
34 | |||
35 | #define COUNT_LEADING_ZEROS_0 BITS_PER_LONG | ||
36 | |||
37 | /** | ||
38 | * count_trailing_zeros - Count the number of zeros from the LSB forwards | ||
39 | * @x: The value | ||
40 | * | ||
41 | * Count the number of trailing zeros from the LSB going towards the MSB in @x. | ||
42 | * | ||
43 | * If the LSB of @x is set, the result is 0. | ||
44 | * If only the MSB of @x is set, then the result is BITS_PER_LONG-1. | ||
45 | * If @x is 0 then the result is COUNT_TRAILING_ZEROS_0. | ||
46 | */ | ||
47 | static inline int count_trailing_zeros(unsigned long x) | ||
48 | { | ||
49 | #define COUNT_TRAILING_ZEROS_0 (-1) | ||
50 | |||
51 | if (sizeof(x) == 4) | ||
52 | return ffs(x); | ||
53 | else | ||
54 | return (x != 0) ? __ffs(x) : COUNT_TRAILING_ZEROS_0; | ||
55 | } | ||
56 | |||
57 | #endif /* _ASM_GENERIC_BITOPS_COUNT_ZEROS_H_ */ | ||
diff --git a/include/asm-generic/module.h b/include/asm-generic/module.h index ed5b44de4c91..14dc41d185a7 100644 --- a/include/asm-generic/module.h +++ b/include/asm-generic/module.h | |||
@@ -5,18 +5,44 @@ | |||
5 | * Many architectures just need a simple module | 5 | * Many architectures just need a simple module |
6 | * loader without arch specific data. | 6 | * loader without arch specific data. |
7 | */ | 7 | */ |
8 | #ifndef CONFIG_HAVE_MOD_ARCH_SPECIFIC | ||
8 | struct mod_arch_specific | 9 | struct mod_arch_specific |
9 | { | 10 | { |
10 | }; | 11 | }; |
12 | #endif | ||
11 | 13 | ||
12 | #ifdef CONFIG_64BIT | 14 | #ifdef CONFIG_64BIT |
13 | #define Elf_Shdr Elf64_Shdr | 15 | #define Elf_Shdr Elf64_Shdr |
14 | #define Elf_Sym Elf64_Sym | 16 | #define Elf_Phdr Elf64_Phdr |
15 | #define Elf_Ehdr Elf64_Ehdr | 17 | #define Elf_Sym Elf64_Sym |
16 | #else | 18 | #define Elf_Dyn Elf64_Dyn |
17 | #define Elf_Shdr Elf32_Shdr | 19 | #define Elf_Ehdr Elf64_Ehdr |
18 | #define Elf_Sym Elf32_Sym | 20 | #define Elf_Addr Elf64_Addr |
19 | #define Elf_Ehdr Elf32_Ehdr | 21 | #ifdef CONFIG_MODULES_USE_ELF_REL |
22 | #define Elf_Rel Elf64_Rel | ||
23 | #endif | ||
24 | #ifdef CONFIG_MODULES_USE_ELF_RELA | ||
25 | #define Elf_Rela Elf64_Rela | ||
26 | #endif | ||
27 | #define ELF_R_TYPE(X) ELF64_R_TYPE(X) | ||
28 | #define ELF_R_SYM(X) ELF64_R_SYM(X) | ||
29 | |||
30 | #else /* CONFIG_64BIT */ | ||
31 | |||
32 | #define Elf_Shdr Elf32_Shdr | ||
33 | #define Elf_Phdr Elf32_Phdr | ||
34 | #define Elf_Sym Elf32_Sym | ||
35 | #define Elf_Dyn Elf32_Dyn | ||
36 | #define Elf_Ehdr Elf32_Ehdr | ||
37 | #define Elf_Addr Elf32_Addr | ||
38 | #ifdef CONFIG_MODULES_USE_ELF_REL | ||
39 | #define Elf_Rel Elf32_Rel | ||
40 | #endif | ||
41 | #ifdef CONFIG_MODULES_USE_ELF_RELA | ||
42 | #define Elf_Rela Elf32_Rela | ||
43 | #endif | ||
44 | #define ELF_R_TYPE(X) ELF32_R_TYPE(X) | ||
45 | #define ELF_R_SYM(X) ELF32_R_SYM(X) | ||
20 | #endif | 46 | #endif |
21 | 47 | ||
22 | #endif /* __ASM_GENERIC_MODULE_H */ | 48 | #endif /* __ASM_GENERIC_MODULE_H */ |
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h new file mode 100644 index 000000000000..f5b0224c9967 --- /dev/null +++ b/include/crypto/public_key.h | |||
@@ -0,0 +1,108 @@ | |||
1 | /* Asymmetric public-key algorithm definitions | ||
2 | * | ||
3 | * See Documentation/crypto/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 | |||
14 | #ifndef _LINUX_PUBLIC_KEY_H | ||
15 | #define _LINUX_PUBLIC_KEY_H | ||
16 | |||
17 | #include <linux/mpi.h> | ||
18 | |||
19 | enum pkey_algo { | ||
20 | PKEY_ALGO_DSA, | ||
21 | PKEY_ALGO_RSA, | ||
22 | PKEY_ALGO__LAST | ||
23 | }; | ||
24 | |||
25 | extern const char *const pkey_algo[PKEY_ALGO__LAST]; | ||
26 | |||
27 | enum pkey_hash_algo { | ||
28 | PKEY_HASH_MD4, | ||
29 | PKEY_HASH_MD5, | ||
30 | PKEY_HASH_SHA1, | ||
31 | PKEY_HASH_RIPE_MD_160, | ||
32 | PKEY_HASH_SHA256, | ||
33 | PKEY_HASH_SHA384, | ||
34 | PKEY_HASH_SHA512, | ||
35 | PKEY_HASH_SHA224, | ||
36 | PKEY_HASH__LAST | ||
37 | }; | ||
38 | |||
39 | extern const char *const pkey_hash_algo[PKEY_HASH__LAST]; | ||
40 | |||
41 | enum pkey_id_type { | ||
42 | PKEY_ID_PGP, /* OpenPGP generated key ID */ | ||
43 | PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */ | ||
44 | PKEY_ID_TYPE__LAST | ||
45 | }; | ||
46 | |||
47 | extern const char *const pkey_id_type[PKEY_ID_TYPE__LAST]; | ||
48 | |||
49 | /* | ||
50 | * Cryptographic data for the public-key subtype of the asymmetric key type. | ||
51 | * | ||
52 | * Note that this may include private part of the key as well as the public | ||
53 | * part. | ||
54 | */ | ||
55 | struct public_key { | ||
56 | const struct public_key_algorithm *algo; | ||
57 | u8 capabilities; | ||
58 | #define PKEY_CAN_ENCRYPT 0x01 | ||
59 | #define PKEY_CAN_DECRYPT 0x02 | ||
60 | #define PKEY_CAN_SIGN 0x04 | ||
61 | #define PKEY_CAN_VERIFY 0x08 | ||
62 | enum pkey_id_type id_type : 8; | ||
63 | union { | ||
64 | MPI mpi[5]; | ||
65 | struct { | ||
66 | MPI p; /* DSA prime */ | ||
67 | MPI q; /* DSA group order */ | ||
68 | MPI g; /* DSA group generator */ | ||
69 | MPI y; /* DSA public-key value = g^x mod p */ | ||
70 | MPI x; /* DSA secret exponent (if present) */ | ||
71 | } dsa; | ||
72 | struct { | ||
73 | MPI n; /* RSA public modulus */ | ||
74 | MPI e; /* RSA public encryption exponent */ | ||
75 | MPI d; /* RSA secret encryption exponent (if present) */ | ||
76 | MPI p; /* RSA secret prime (if present) */ | ||
77 | MPI q; /* RSA secret prime (if present) */ | ||
78 | } rsa; | ||
79 | }; | ||
80 | }; | ||
81 | |||
82 | extern void public_key_destroy(void *payload); | ||
83 | |||
84 | /* | ||
85 | * Public key cryptography signature data | ||
86 | */ | ||
87 | struct public_key_signature { | ||
88 | u8 *digest; | ||
89 | u8 digest_size; /* Number of bytes in digest */ | ||
90 | u8 nr_mpi; /* Occupancy of mpi[] */ | ||
91 | enum pkey_hash_algo pkey_hash_algo : 8; | ||
92 | union { | ||
93 | MPI mpi[2]; | ||
94 | struct { | ||
95 | MPI s; /* m^d mod n */ | ||
96 | } rsa; | ||
97 | struct { | ||
98 | MPI r; | ||
99 | MPI s; | ||
100 | } dsa; | ||
101 | }; | ||
102 | }; | ||
103 | |||
104 | struct key; | ||
105 | extern int verify_signature(const struct key *key, | ||
106 | const struct public_key_signature *sig); | ||
107 | |||
108 | #endif /* _LINUX_PUBLIC_KEY_H */ | ||
diff --git a/include/keys/asymmetric-parser.h b/include/keys/asymmetric-parser.h new file mode 100644 index 000000000000..09b3b4807f5c --- /dev/null +++ b/include/keys/asymmetric-parser.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* Asymmetric public-key cryptography data parser | ||
2 | * | ||
3 | * See Documentation/crypto/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 | |||
14 | #ifndef _KEYS_ASYMMETRIC_PARSER_H | ||
15 | #define _KEYS_ASYMMETRIC_PARSER_H | ||
16 | |||
17 | /* | ||
18 | * Key data parser. Called during key instantiation. | ||
19 | */ | ||
20 | struct asymmetric_key_parser { | ||
21 | struct list_head link; | ||
22 | struct module *owner; | ||
23 | const char *name; | ||
24 | |||
25 | /* Attempt to parse a key from the data blob passed to add_key() or | ||
26 | * keyctl_instantiate(). Should also generate a proposed description | ||
27 | * that the caller can optionally use for the key. | ||
28 | * | ||
29 | * Return EBADMSG if not recognised. | ||
30 | */ | ||
31 | int (*parse)(struct key_preparsed_payload *prep); | ||
32 | }; | ||
33 | |||
34 | extern int register_asymmetric_key_parser(struct asymmetric_key_parser *); | ||
35 | extern void unregister_asymmetric_key_parser(struct asymmetric_key_parser *); | ||
36 | |||
37 | #endif /* _KEYS_ASYMMETRIC_PARSER_H */ | ||
diff --git a/include/keys/asymmetric-subtype.h b/include/keys/asymmetric-subtype.h new file mode 100644 index 000000000000..4b840e822209 --- /dev/null +++ b/include/keys/asymmetric-subtype.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* Asymmetric public-key cryptography key subtype | ||
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 | |||
14 | #ifndef _KEYS_ASYMMETRIC_SUBTYPE_H | ||
15 | #define _KEYS_ASYMMETRIC_SUBTYPE_H | ||
16 | |||
17 | #include <linux/seq_file.h> | ||
18 | #include <keys/asymmetric-type.h> | ||
19 | |||
20 | struct public_key_signature; | ||
21 | |||
22 | /* | ||
23 | * Keys of this type declare a subtype that indicates the handlers and | ||
24 | * capabilities. | ||
25 | */ | ||
26 | struct asymmetric_key_subtype { | ||
27 | struct module *owner; | ||
28 | const char *name; | ||
29 | unsigned short name_len; /* length of name */ | ||
30 | |||
31 | /* Describe a key of this subtype for /proc/keys */ | ||
32 | void (*describe)(const struct key *key, struct seq_file *m); | ||
33 | |||
34 | /* Destroy a key of this subtype */ | ||
35 | void (*destroy)(void *payload); | ||
36 | |||
37 | /* Verify the signature on a key of this subtype (optional) */ | ||
38 | int (*verify_signature)(const struct key *key, | ||
39 | const struct public_key_signature *sig); | ||
40 | }; | ||
41 | |||
42 | /** | ||
43 | * asymmetric_key_subtype - Get the subtype from an asymmetric key | ||
44 | * @key: The key of interest. | ||
45 | * | ||
46 | * Retrieves and returns the subtype pointer of the asymmetric key from the | ||
47 | * type-specific data attached to the key. | ||
48 | */ | ||
49 | static inline | ||
50 | struct asymmetric_key_subtype *asymmetric_key_subtype(const struct key *key) | ||
51 | { | ||
52 | return key->type_data.p[0]; | ||
53 | } | ||
54 | |||
55 | #endif /* _KEYS_ASYMMETRIC_SUBTYPE_H */ | ||
diff --git a/include/keys/asymmetric-type.h b/include/keys/asymmetric-type.h new file mode 100644 index 000000000000..7dd473496180 --- /dev/null +++ b/include/keys/asymmetric-type.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* Asymmetric Public-key cryptography key type interface | ||
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 | |||
14 | #ifndef _KEYS_ASYMMETRIC_TYPE_H | ||
15 | #define _KEYS_ASYMMETRIC_TYPE_H | ||
16 | |||
17 | #include <linux/key-type.h> | ||
18 | |||
19 | extern struct key_type key_type_asymmetric; | ||
20 | |||
21 | /* | ||
22 | * The payload is at the discretion of the subtype. | ||
23 | */ | ||
24 | |||
25 | #endif /* _KEYS_ASYMMETRIC_TYPE_H */ | ||
diff --git a/include/keys/user-type.h b/include/keys/user-type.h index bc9ec1d7698c..5e452c84f1e6 100644 --- a/include/keys/user-type.h +++ b/include/keys/user-type.h | |||
@@ -35,8 +35,10 @@ struct user_key_payload { | |||
35 | extern struct key_type key_type_user; | 35 | extern struct key_type key_type_user; |
36 | extern struct key_type key_type_logon; | 36 | extern struct key_type key_type_logon; |
37 | 37 | ||
38 | extern int user_instantiate(struct key *key, const void *data, size_t datalen); | 38 | struct key_preparsed_payload; |
39 | extern int user_update(struct key *key, const void *data, size_t datalen); | 39 | |
40 | extern int user_instantiate(struct key *key, struct key_preparsed_payload *prep); | ||
41 | extern int user_update(struct key *key, struct key_preparsed_payload *prep); | ||
40 | extern int user_match(const struct key *key, const void *criterion); | 42 | extern int user_match(const struct key *key, const void *criterion); |
41 | extern void user_revoke(struct key *key); | 43 | extern void user_revoke(struct key *key); |
42 | extern void user_destroy(struct key *key); | 44 | extern void user_destroy(struct key *key); |
diff --git a/include/linux/asn1.h b/include/linux/asn1.h new file mode 100644 index 000000000000..5c3f4e4b9a23 --- /dev/null +++ b/include/linux/asn1.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /* ASN.1 BER/DER/CER encoding definitions | ||
2 | * | ||
3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _LINUX_ASN1_H | ||
13 | #define _LINUX_ASN1_H | ||
14 | |||
15 | /* Class */ | ||
16 | enum asn1_class { | ||
17 | ASN1_UNIV = 0, /* Universal */ | ||
18 | ASN1_APPL = 1, /* Application */ | ||
19 | ASN1_CONT = 2, /* Context */ | ||
20 | ASN1_PRIV = 3 /* Private */ | ||
21 | }; | ||
22 | #define ASN1_CLASS_BITS 0xc0 | ||
23 | |||
24 | |||
25 | enum asn1_method { | ||
26 | ASN1_PRIM = 0, /* Primitive */ | ||
27 | ASN1_CONS = 1 /* Constructed */ | ||
28 | }; | ||
29 | #define ASN1_CONS_BIT 0x20 | ||
30 | |||
31 | /* Tag */ | ||
32 | enum asn1_tag { | ||
33 | ASN1_EOC = 0, /* End Of Contents or N/A */ | ||
34 | ASN1_BOOL = 1, /* Boolean */ | ||
35 | ASN1_INT = 2, /* Integer */ | ||
36 | ASN1_BTS = 3, /* Bit String */ | ||
37 | ASN1_OTS = 4, /* Octet String */ | ||
38 | ASN1_NULL = 5, /* Null */ | ||
39 | ASN1_OID = 6, /* Object Identifier */ | ||
40 | ASN1_ODE = 7, /* Object Description */ | ||
41 | ASN1_EXT = 8, /* External */ | ||
42 | ASN1_REAL = 9, /* Real float */ | ||
43 | ASN1_ENUM = 10, /* Enumerated */ | ||
44 | ASN1_EPDV = 11, /* Embedded PDV */ | ||
45 | ASN1_UTF8STR = 12, /* UTF8 String */ | ||
46 | ASN1_RELOID = 13, /* Relative OID */ | ||
47 | /* 14 - Reserved */ | ||
48 | /* 15 - Reserved */ | ||
49 | ASN1_SEQ = 16, /* Sequence and Sequence of */ | ||
50 | ASN1_SET = 17, /* Set and Set of */ | ||
51 | ASN1_NUMSTR = 18, /* Numerical String */ | ||
52 | ASN1_PRNSTR = 19, /* Printable String */ | ||
53 | ASN1_TEXSTR = 20, /* T61 String / Teletext String */ | ||
54 | ASN1_VIDSTR = 21, /* Videotex String */ | ||
55 | ASN1_IA5STR = 22, /* IA5 String */ | ||
56 | ASN1_UNITIM = 23, /* Universal Time */ | ||
57 | ASN1_GENTIM = 24, /* General Time */ | ||
58 | ASN1_GRASTR = 25, /* Graphic String */ | ||
59 | ASN1_VISSTR = 26, /* Visible String */ | ||
60 | ASN1_GENSTR = 27, /* General String */ | ||
61 | ASN1_UNISTR = 28, /* Universal String */ | ||
62 | ASN1_CHRSTR = 29, /* Character String */ | ||
63 | ASN1_BMPSTR = 30, /* BMP String */ | ||
64 | ASN1_LONG_TAG = 31 /* Long form tag */ | ||
65 | }; | ||
66 | |||
67 | #endif /* _LINUX_ASN1_H */ | ||
diff --git a/include/linux/asn1_ber_bytecode.h b/include/linux/asn1_ber_bytecode.h new file mode 100644 index 000000000000..945d44ae529c --- /dev/null +++ b/include/linux/asn1_ber_bytecode.h | |||
@@ -0,0 +1,87 @@ | |||
1 | /* ASN.1 BER/DER/CER parsing state machine internal definitions | ||
2 | * | ||
3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _LINUX_ASN1_BER_BYTECODE_H | ||
13 | #define _LINUX_ASN1_BER_BYTECODE_H | ||
14 | |||
15 | #ifdef __KERNEL__ | ||
16 | #include <linux/types.h> | ||
17 | #endif | ||
18 | #include <linux/asn1.h> | ||
19 | |||
20 | typedef int (*asn1_action_t)(void *context, | ||
21 | size_t hdrlen, /* In case of ANY type */ | ||
22 | unsigned char tag, /* In case of ANY type */ | ||
23 | const void *value, size_t vlen); | ||
24 | |||
25 | struct asn1_decoder { | ||
26 | const unsigned char *machine; | ||
27 | size_t machlen; | ||
28 | const asn1_action_t *actions; | ||
29 | }; | ||
30 | |||
31 | enum asn1_opcode { | ||
32 | /* The tag-matching ops come first and the odd-numbered slots | ||
33 | * are for OR_SKIP ops. | ||
34 | */ | ||
35 | #define ASN1_OP_MATCH__SKIP 0x01 | ||
36 | #define ASN1_OP_MATCH__ACT 0x02 | ||
37 | #define ASN1_OP_MATCH__JUMP 0x04 | ||
38 | #define ASN1_OP_MATCH__ANY 0x08 | ||
39 | #define ASN1_OP_MATCH__COND 0x10 | ||
40 | |||
41 | ASN1_OP_MATCH = 0x00, | ||
42 | ASN1_OP_MATCH_OR_SKIP = 0x01, | ||
43 | ASN1_OP_MATCH_ACT = 0x02, | ||
44 | ASN1_OP_MATCH_ACT_OR_SKIP = 0x03, | ||
45 | ASN1_OP_MATCH_JUMP = 0x04, | ||
46 | ASN1_OP_MATCH_JUMP_OR_SKIP = 0x05, | ||
47 | ASN1_OP_MATCH_ANY = 0x08, | ||
48 | ASN1_OP_MATCH_ANY_ACT = 0x0a, | ||
49 | /* Everything before here matches unconditionally */ | ||
50 | |||
51 | ASN1_OP_COND_MATCH_OR_SKIP = 0x11, | ||
52 | ASN1_OP_COND_MATCH_ACT_OR_SKIP = 0x13, | ||
53 | ASN1_OP_COND_MATCH_JUMP_OR_SKIP = 0x15, | ||
54 | ASN1_OP_COND_MATCH_ANY = 0x18, | ||
55 | ASN1_OP_COND_MATCH_ANY_ACT = 0x1a, | ||
56 | |||
57 | /* Everything before here will want a tag from the data */ | ||
58 | #define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT | ||
59 | |||
60 | /* These are here to help fill up space */ | ||
61 | ASN1_OP_COND_FAIL = 0x1b, | ||
62 | ASN1_OP_COMPLETE = 0x1c, | ||
63 | ASN1_OP_ACT = 0x1d, | ||
64 | ASN1_OP_RETURN = 0x1e, | ||
65 | |||
66 | /* The following eight have bit 0 -> SET, 1 -> OF, 2 -> ACT */ | ||
67 | ASN1_OP_END_SEQ = 0x20, | ||
68 | ASN1_OP_END_SET = 0x21, | ||
69 | ASN1_OP_END_SEQ_OF = 0x22, | ||
70 | ASN1_OP_END_SET_OF = 0x23, | ||
71 | ASN1_OP_END_SEQ_ACT = 0x24, | ||
72 | ASN1_OP_END_SET_ACT = 0x25, | ||
73 | ASN1_OP_END_SEQ_OF_ACT = 0x26, | ||
74 | ASN1_OP_END_SET_OF_ACT = 0x27, | ||
75 | #define ASN1_OP_END__SET 0x01 | ||
76 | #define ASN1_OP_END__OF 0x02 | ||
77 | #define ASN1_OP_END__ACT 0x04 | ||
78 | |||
79 | ASN1_OP__NR | ||
80 | }; | ||
81 | |||
82 | #define _tag(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | ASN1_##TAG) | ||
83 | #define _tagn(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | TAG) | ||
84 | #define _jump_target(N) (N) | ||
85 | #define _action(N) (N) | ||
86 | |||
87 | #endif /* _LINUX_ASN1_BER_BYTECODE_H */ | ||
diff --git a/include/linux/asn1_decoder.h b/include/linux/asn1_decoder.h new file mode 100644 index 000000000000..fa2ff5bc0483 --- /dev/null +++ b/include/linux/asn1_decoder.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* ASN.1 decoder | ||
2 | * | ||
3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _LINUX_ASN1_DECODER_H | ||
13 | #define _LINUX_ASN1_DECODER_H | ||
14 | |||
15 | #include <linux/asn1.h> | ||
16 | |||
17 | struct asn1_decoder; | ||
18 | |||
19 | extern int asn1_ber_decoder(const struct asn1_decoder *decoder, | ||
20 | void *context, | ||
21 | const unsigned char *data, | ||
22 | size_t datalen); | ||
23 | |||
24 | #endif /* _LINUX_ASN1_DECODER_H */ | ||
diff --git a/include/linux/key-type.h b/include/linux/key-type.h index f0c651cda7b0..518a53afb9ea 100644 --- a/include/linux/key-type.h +++ b/include/linux/key-type.h | |||
@@ -26,6 +26,27 @@ struct key_construction { | |||
26 | struct key *authkey;/* authorisation for key being constructed */ | 26 | struct key *authkey;/* authorisation for key being constructed */ |
27 | }; | 27 | }; |
28 | 28 | ||
29 | /* | ||
30 | * Pre-parsed payload, used by key add, update and instantiate. | ||
31 | * | ||
32 | * This struct will be cleared and data and datalen will be set with the data | ||
33 | * and length parameters from the caller and quotalen will be set from | ||
34 | * def_datalen from the key type. Then if the preparse() op is provided by the | ||
35 | * key type, that will be called. Then the struct will be passed to the | ||
36 | * instantiate() or the update() op. | ||
37 | * | ||
38 | * If the preparse() op is given, the free_preparse() op will be called to | ||
39 | * clear the contents. | ||
40 | */ | ||
41 | struct key_preparsed_payload { | ||
42 | char *description; /* Proposed key description (or NULL) */ | ||
43 | void *type_data[2]; /* Private key-type data */ | ||
44 | void *payload; /* Proposed payload */ | ||
45 | const void *data; /* Raw data */ | ||
46 | size_t datalen; /* Raw datalen */ | ||
47 | size_t quotalen; /* Quota length for proposed payload */ | ||
48 | }; | ||
49 | |||
29 | typedef int (*request_key_actor_t)(struct key_construction *key, | 50 | typedef int (*request_key_actor_t)(struct key_construction *key, |
30 | const char *op, void *aux); | 51 | const char *op, void *aux); |
31 | 52 | ||
@@ -45,18 +66,28 @@ struct key_type { | |||
45 | /* vet a description */ | 66 | /* vet a description */ |
46 | int (*vet_description)(const char *description); | 67 | int (*vet_description)(const char *description); |
47 | 68 | ||
69 | /* Preparse the data blob from userspace that is to be the payload, | ||
70 | * generating a proposed description and payload that will be handed to | ||
71 | * the instantiate() and update() ops. | ||
72 | */ | ||
73 | int (*preparse)(struct key_preparsed_payload *prep); | ||
74 | |||
75 | /* Free a preparse data structure. | ||
76 | */ | ||
77 | void (*free_preparse)(struct key_preparsed_payload *prep); | ||
78 | |||
48 | /* instantiate a key of this type | 79 | /* instantiate a key of this type |
49 | * - this method should call key_payload_reserve() to determine if the | 80 | * - this method should call key_payload_reserve() to determine if the |
50 | * user's quota will hold the payload | 81 | * user's quota will hold the payload |
51 | */ | 82 | */ |
52 | int (*instantiate)(struct key *key, const void *data, size_t datalen); | 83 | int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); |
53 | 84 | ||
54 | /* update a key of this type (optional) | 85 | /* update a key of this type (optional) |
55 | * - this method should call key_payload_reserve() to recalculate the | 86 | * - this method should call key_payload_reserve() to recalculate the |
56 | * quota consumption | 87 | * quota consumption |
57 | * - the key must be locked against read when modifying | 88 | * - the key must be locked against read when modifying |
58 | */ | 89 | */ |
59 | int (*update)(struct key *key, const void *data, size_t datalen); | 90 | int (*update)(struct key *key, struct key_preparsed_payload *prep); |
60 | 91 | ||
61 | /* match a key against a description */ | 92 | /* match a key against a description */ |
62 | int (*match)(const struct key *key, const void *desc); | 93 | int (*match)(const struct key *key, const void *desc); |
diff --git a/include/linux/module.h b/include/linux/module.h index fbcafe2ee13e..7760c6d344a3 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -21,6 +21,9 @@ | |||
21 | #include <linux/percpu.h> | 21 | #include <linux/percpu.h> |
22 | #include <asm/module.h> | 22 | #include <asm/module.h> |
23 | 23 | ||
24 | /* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */ | ||
25 | #define MODULE_SIG_STRING "~Module signature appended~\n" | ||
26 | |||
24 | /* Not Yet Implemented */ | 27 | /* Not Yet Implemented */ |
25 | #define MODULE_SUPPORTED_DEVICE(name) | 28 | #define MODULE_SUPPORTED_DEVICE(name) |
26 | 29 | ||
@@ -260,6 +263,11 @@ struct module | |||
260 | const unsigned long *unused_gpl_crcs; | 263 | const unsigned long *unused_gpl_crcs; |
261 | #endif | 264 | #endif |
262 | 265 | ||
266 | #ifdef CONFIG_MODULE_SIG | ||
267 | /* Signature was verified. */ | ||
268 | bool sig_ok; | ||
269 | #endif | ||
270 | |||
263 | /* symbols that will be GPL-only in the near future. */ | 271 | /* symbols that will be GPL-only in the near future. */ |
264 | const struct kernel_symbol *gpl_future_syms; | 272 | const struct kernel_symbol *gpl_future_syms; |
265 | const unsigned long *gpl_future_crcs; | 273 | const unsigned long *gpl_future_crcs; |
diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h index b2be02ebf453..560ca53a75fa 100644 --- a/include/linux/moduleloader.h +++ b/include/linux/moduleloader.h | |||
@@ -28,21 +28,49 @@ void *module_alloc(unsigned long size); | |||
28 | /* Free memory returned from module_alloc. */ | 28 | /* Free memory returned from module_alloc. */ |
29 | void module_free(struct module *mod, void *module_region); | 29 | void module_free(struct module *mod, void *module_region); |
30 | 30 | ||
31 | /* Apply the given relocation to the (simplified) ELF. Return -error | 31 | /* |
32 | or 0. */ | 32 | * Apply the given relocation to the (simplified) ELF. Return -error |
33 | * or 0. | ||
34 | */ | ||
35 | #ifdef CONFIG_MODULES_USE_ELF_REL | ||
33 | int apply_relocate(Elf_Shdr *sechdrs, | 36 | int apply_relocate(Elf_Shdr *sechdrs, |
34 | const char *strtab, | 37 | const char *strtab, |
35 | unsigned int symindex, | 38 | unsigned int symindex, |
36 | unsigned int relsec, | 39 | unsigned int relsec, |
37 | struct module *mod); | 40 | struct module *mod); |
41 | #else | ||
42 | static inline int apply_relocate(Elf_Shdr *sechdrs, | ||
43 | const char *strtab, | ||
44 | unsigned int symindex, | ||
45 | unsigned int relsec, | ||
46 | struct module *me) | ||
47 | { | ||
48 | printk(KERN_ERR "module %s: REL relocation unsupported\n", me->name); | ||
49 | return -ENOEXEC; | ||
50 | } | ||
51 | #endif | ||
38 | 52 | ||
39 | /* Apply the given add relocation to the (simplified) ELF. Return | 53 | /* |
40 | -error or 0 */ | 54 | * Apply the given add relocation to the (simplified) ELF. Return |
55 | * -error or 0 | ||
56 | */ | ||
57 | #ifdef CONFIG_MODULES_USE_ELF_RELA | ||
41 | int apply_relocate_add(Elf_Shdr *sechdrs, | 58 | int apply_relocate_add(Elf_Shdr *sechdrs, |
42 | const char *strtab, | 59 | const char *strtab, |
43 | unsigned int symindex, | 60 | unsigned int symindex, |
44 | unsigned int relsec, | 61 | unsigned int relsec, |
45 | struct module *mod); | 62 | struct module *mod); |
63 | #else | ||
64 | static inline int apply_relocate_add(Elf_Shdr *sechdrs, | ||
65 | const char *strtab, | ||
66 | unsigned int symindex, | ||
67 | unsigned int relsec, | ||
68 | struct module *me) | ||
69 | { | ||
70 | printk(KERN_ERR "module %s: REL relocation unsupported\n", me->name); | ||
71 | return -ENOEXEC; | ||
72 | } | ||
73 | #endif | ||
46 | 74 | ||
47 | /* Any final processing of module before access. Return -error or 0. */ | 75 | /* Any final processing of module before access. Return -error or 0. */ |
48 | int module_finalize(const Elf_Ehdr *hdr, | 76 | int module_finalize(const Elf_Ehdr *hdr, |
diff --git a/include/linux/mpi.h b/include/linux/mpi.h index d02cca6cc8ce..5af1b81def49 100644 --- a/include/linux/mpi.h +++ b/include/linux/mpi.h | |||
@@ -76,6 +76,7 @@ void mpi_swap(MPI a, MPI b); | |||
76 | 76 | ||
77 | /*-- mpicoder.c --*/ | 77 | /*-- mpicoder.c --*/ |
78 | MPI do_encode_md(const void *sha_buffer, unsigned nbits); | 78 | MPI do_encode_md(const void *sha_buffer, unsigned nbits); |
79 | MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes); | ||
79 | MPI mpi_read_from_buffer(const void *buffer, unsigned *ret_nread); | 80 | MPI mpi_read_from_buffer(const void *buffer, unsigned *ret_nread); |
80 | int mpi_fromstr(MPI val, const char *str); | 81 | int mpi_fromstr(MPI val, const char *str); |
81 | u32 mpi_get_keyid(MPI a, u32 *keyid); | 82 | u32 mpi_get_keyid(MPI a, u32 *keyid); |
diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h new file mode 100644 index 000000000000..6926db724258 --- /dev/null +++ b/include/linux/oid_registry.h | |||
@@ -0,0 +1,92 @@ | |||
1 | /* ASN.1 Object identifier (OID) registry | ||
2 | * | ||
3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _LINUX_OID_REGISTRY_H | ||
13 | #define _LINUX_OID_REGISTRY_H | ||
14 | |||
15 | #include <linux/types.h> | ||
16 | |||
17 | /* | ||
18 | * OIDs are turned into these values if possible, or OID__NR if not held here. | ||
19 | * | ||
20 | * NOTE! Do not mess with the format of each line as this is read by | ||
21 | * build_OID_registry.pl to generate the data for look_up_OID(). | ||
22 | */ | ||
23 | enum OID { | ||
24 | OID_id_dsa_with_sha1, /* 1.2.840.10030.4.3 */ | ||
25 | OID_id_dsa, /* 1.2.840.10040.4.1 */ | ||
26 | OID_id_ecdsa_with_sha1, /* 1.2.840.10045.4.1 */ | ||
27 | OID_id_ecPublicKey, /* 1.2.840.10045.2.1 */ | ||
28 | |||
29 | /* PKCS#1 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1)} */ | ||
30 | OID_rsaEncryption, /* 1.2.840.113549.1.1.1 */ | ||
31 | OID_md2WithRSAEncryption, /* 1.2.840.113549.1.1.2 */ | ||
32 | OID_md3WithRSAEncryption, /* 1.2.840.113549.1.1.3 */ | ||
33 | OID_md4WithRSAEncryption, /* 1.2.840.113549.1.1.4 */ | ||
34 | OID_sha1WithRSAEncryption, /* 1.2.840.113549.1.1.5 */ | ||
35 | OID_sha256WithRSAEncryption, /* 1.2.840.113549.1.1.11 */ | ||
36 | OID_sha384WithRSAEncryption, /* 1.2.840.113549.1.1.12 */ | ||
37 | OID_sha512WithRSAEncryption, /* 1.2.840.113549.1.1.13 */ | ||
38 | OID_sha224WithRSAEncryption, /* 1.2.840.113549.1.1.14 */ | ||
39 | /* PKCS#7 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-7(7)} */ | ||
40 | OID_data, /* 1.2.840.113549.1.7.1 */ | ||
41 | OID_signed_data, /* 1.2.840.113549.1.7.2 */ | ||
42 | /* PKCS#9 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)} */ | ||
43 | OID_email_address, /* 1.2.840.113549.1.9.1 */ | ||
44 | OID_content_type, /* 1.2.840.113549.1.9.3 */ | ||
45 | OID_messageDigest, /* 1.2.840.113549.1.9.4 */ | ||
46 | OID_signingTime, /* 1.2.840.113549.1.9.5 */ | ||
47 | OID_smimeCapabilites, /* 1.2.840.113549.1.9.15 */ | ||
48 | OID_smimeAuthenticatedAttrs, /* 1.2.840.113549.1.9.16.2.11 */ | ||
49 | |||
50 | /* {iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2)} */ | ||
51 | OID_md2, /* 1.2.840.113549.2.2 */ | ||
52 | OID_md4, /* 1.2.840.113549.2.4 */ | ||
53 | OID_md5, /* 1.2.840.113549.2.5 */ | ||
54 | |||
55 | OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */ | ||
56 | OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */ | ||
57 | OID_sha1, /* 1.3.14.3.2.26 */ | ||
58 | |||
59 | /* Distinguished Name attribute IDs [RFC 2256] */ | ||
60 | OID_commonName, /* 2.5.4.3 */ | ||
61 | OID_surname, /* 2.5.4.4 */ | ||
62 | OID_countryName, /* 2.5.4.6 */ | ||
63 | OID_locality, /* 2.5.4.7 */ | ||
64 | OID_stateOrProvinceName, /* 2.5.4.8 */ | ||
65 | OID_organizationName, /* 2.5.4.10 */ | ||
66 | OID_organizationUnitName, /* 2.5.4.11 */ | ||
67 | OID_title, /* 2.5.4.12 */ | ||
68 | OID_description, /* 2.5.4.13 */ | ||
69 | OID_name, /* 2.5.4.41 */ | ||
70 | OID_givenName, /* 2.5.4.42 */ | ||
71 | OID_initials, /* 2.5.4.43 */ | ||
72 | OID_generationalQualifier, /* 2.5.4.44 */ | ||
73 | |||
74 | /* Certificate extension IDs */ | ||
75 | OID_subjectKeyIdentifier, /* 2.5.29.14 */ | ||
76 | OID_keyUsage, /* 2.5.29.15 */ | ||
77 | OID_subjectAltName, /* 2.5.29.17 */ | ||
78 | OID_issuerAltName, /* 2.5.29.18 */ | ||
79 | OID_basicConstraints, /* 2.5.29.19 */ | ||
80 | OID_crlDistributionPoints, /* 2.5.29.31 */ | ||
81 | OID_certPolicies, /* 2.5.29.32 */ | ||
82 | OID_authorityKeyIdentifier, /* 2.5.29.35 */ | ||
83 | OID_extKeyUsage, /* 2.5.29.37 */ | ||
84 | |||
85 | OID__NR | ||
86 | }; | ||
87 | |||
88 | extern enum OID look_up_OID(const void *data, size_t datasize); | ||
89 | extern int sprint_oid(const void *, size_t, char *, size_t); | ||
90 | extern int sprint_OID(enum OID, char *, size_t); | ||
91 | |||
92 | #endif /* _LINUX_OID_REGISTRY_H */ | ||
diff --git a/init/Kconfig b/init/Kconfig index 89e4cf672dfe..6fdd6e339326 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -1574,6 +1574,66 @@ config MODULE_SRCVERSION_ALL | |||
1574 | the version). With this option, such a "srcversion" field | 1574 | the version). With this option, such a "srcversion" field |
1575 | will be created for all modules. If unsure, say N. | 1575 | will be created for all modules. If unsure, say N. |
1576 | 1576 | ||
1577 | config MODULE_SIG | ||
1578 | bool "Module signature verification" | ||
1579 | depends on MODULES | ||
1580 | select KEYS | ||
1581 | select CRYPTO | ||
1582 | select ASYMMETRIC_KEY_TYPE | ||
1583 | select ASYMMETRIC_PUBLIC_KEY_SUBTYPE | ||
1584 | select PUBLIC_KEY_ALGO_RSA | ||
1585 | select ASN1 | ||
1586 | select OID_REGISTRY | ||
1587 | select X509_CERTIFICATE_PARSER | ||
1588 | help | ||
1589 | Check modules for valid signatures upon load: the signature | ||
1590 | is simply appended to the module. For more information see | ||
1591 | Documentation/module-signing.txt. | ||
1592 | |||
1593 | !!!WARNING!!! If you enable this option, you MUST make sure that the | ||
1594 | module DOES NOT get stripped after being signed. This includes the | ||
1595 | debuginfo strip done by some packagers (such as rpmbuild) and | ||
1596 | inclusion into an initramfs that wants the module size reduced. | ||
1597 | |||
1598 | config MODULE_SIG_FORCE | ||
1599 | bool "Require modules to be validly signed" | ||
1600 | depends on MODULE_SIG | ||
1601 | help | ||
1602 | Reject unsigned modules or signed modules for which we don't have a | ||
1603 | key. Without this, such modules will simply taint the kernel. | ||
1604 | |||
1605 | choice | ||
1606 | prompt "Which hash algorithm should modules be signed with?" | ||
1607 | depends on MODULE_SIG | ||
1608 | help | ||
1609 | This determines which sort of hashing algorithm will be used during | ||
1610 | signature generation. This algorithm _must_ be built into the kernel | ||
1611 | directly so that signature verification can take place. It is not | ||
1612 | possible to load a signed module containing the algorithm to check | ||
1613 | the signature on that module. | ||
1614 | |||
1615 | config MODULE_SIG_SHA1 | ||
1616 | bool "Sign modules with SHA-1" | ||
1617 | select CRYPTO_SHA1 | ||
1618 | |||
1619 | config MODULE_SIG_SHA224 | ||
1620 | bool "Sign modules with SHA-224" | ||
1621 | select CRYPTO_SHA256 | ||
1622 | |||
1623 | config MODULE_SIG_SHA256 | ||
1624 | bool "Sign modules with SHA-256" | ||
1625 | select CRYPTO_SHA256 | ||
1626 | |||
1627 | config MODULE_SIG_SHA384 | ||
1628 | bool "Sign modules with SHA-384" | ||
1629 | select CRYPTO_SHA512 | ||
1630 | |||
1631 | config MODULE_SIG_SHA512 | ||
1632 | bool "Sign modules with SHA-512" | ||
1633 | select CRYPTO_SHA512 | ||
1634 | |||
1635 | endchoice | ||
1636 | |||
1577 | endif # MODULES | 1637 | endif # MODULES |
1578 | 1638 | ||
1579 | config INIT_ALL_POSSIBLE | 1639 | config INIT_ALL_POSSIBLE |
@@ -1607,4 +1667,12 @@ config PADATA | |||
1607 | config BROKEN_RODATA | 1667 | config BROKEN_RODATA |
1608 | bool | 1668 | bool |
1609 | 1669 | ||
1670 | config ASN1 | ||
1671 | tristate | ||
1672 | help | ||
1673 | Build a simple ASN.1 grammar compiler that produces a bytecode output | ||
1674 | that can be interpreted by the ASN.1 stream decoder and used to | ||
1675 | inform it as to what tags are to be expected in a stream and what | ||
1676 | functions to call on what tags. | ||
1677 | |||
1610 | source "kernel/Kconfig.locks" | 1678 | source "kernel/Kconfig.locks" |
diff --git a/kernel/Makefile b/kernel/Makefile index 5404911eaee9..0dfeca4324ee 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
@@ -54,6 +54,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o | |||
54 | obj-$(CONFIG_PROVE_LOCKING) += spinlock.o | 54 | obj-$(CONFIG_PROVE_LOCKING) += spinlock.o |
55 | obj-$(CONFIG_UID16) += uid16.o | 55 | obj-$(CONFIG_UID16) += uid16.o |
56 | obj-$(CONFIG_MODULES) += module.o | 56 | obj-$(CONFIG_MODULES) += module.o |
57 | obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o | ||
57 | obj-$(CONFIG_KALLSYMS) += kallsyms.o | 58 | obj-$(CONFIG_KALLSYMS) += kallsyms.o |
58 | obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o | 59 | obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o |
59 | obj-$(CONFIG_KEXEC) += kexec.o | 60 | obj-$(CONFIG_KEXEC) += kexec.o |
@@ -130,3 +131,79 @@ quiet_cmd_timeconst = TIMEC $@ | |||
130 | targets += timeconst.h | 131 | targets += timeconst.h |
131 | $(obj)/timeconst.h: $(src)/timeconst.pl FORCE | 132 | $(obj)/timeconst.h: $(src)/timeconst.pl FORCE |
132 | $(call if_changed,timeconst) | 133 | $(call if_changed,timeconst) |
134 | |||
135 | ifeq ($(CONFIG_MODULE_SIG),y) | ||
136 | # | ||
137 | # Pull the signing certificate and any extra certificates into the kernel | ||
138 | # | ||
139 | extra_certificates: | ||
140 | touch $@ | ||
141 | |||
142 | kernel/modsign_pubkey.o: signing_key.x509 extra_certificates | ||
143 | |||
144 | ############################################################################### | ||
145 | # | ||
146 | # If module signing is requested, say by allyesconfig, but a key has not been | ||
147 | # supplied, then one will need to be generated to make sure the build does not | ||
148 | # fail and that the kernel may be used afterwards. | ||
149 | # | ||
150 | ############################################################################### | ||
151 | sign_key_with_hash := | ||
152 | ifeq ($(CONFIG_MODULE_SIG_SHA1),y) | ||
153 | sign_key_with_hash := -sha1 | ||
154 | endif | ||
155 | ifeq ($(CONFIG_MODULE_SIG_SHA224),y) | ||
156 | sign_key_with_hash := -sha224 | ||
157 | endif | ||
158 | ifeq ($(CONFIG_MODULE_SIG_SHA256),y) | ||
159 | sign_key_with_hash := -sha256 | ||
160 | endif | ||
161 | ifeq ($(CONFIG_MODULE_SIG_SHA384),y) | ||
162 | sign_key_with_hash := -sha384 | ||
163 | endif | ||
164 | ifeq ($(CONFIG_MODULE_SIG_SHA512),y) | ||
165 | sign_key_with_hash := -sha512 | ||
166 | endif | ||
167 | ifeq ($(sign_key_with_hash),) | ||
168 | $(error Could not determine digest type to use from kernel config) | ||
169 | endif | ||
170 | |||
171 | signing_key.priv signing_key.x509: x509.genkey | ||
172 | @echo "###" | ||
173 | @echo "### Now generating an X.509 key pair to be used for signing modules." | ||
174 | @echo "###" | ||
175 | @echo "### If this takes a long time, you might wish to run rngd in the" | ||
176 | @echo "### background to keep the supply of entropy topped up. It" | ||
177 | @echo "### needs to be run as root, and should use a hardware random" | ||
178 | @echo "### number generator if one is available, eg:" | ||
179 | @echo "###" | ||
180 | @echo "### rngd -r /dev/hwrandom" | ||
181 | @echo "###" | ||
182 | openssl req -new -nodes -utf8 $(sign_key_with_hash) -days 36500 -batch \ | ||
183 | -x509 -config x509.genkey \ | ||
184 | -outform DER -out signing_key.x509 \ | ||
185 | -keyout signing_key.priv | ||
186 | @echo "###" | ||
187 | @echo "### Key pair generated." | ||
188 | @echo "###" | ||
189 | |||
190 | x509.genkey: | ||
191 | @echo Generating X.509 key generation config | ||
192 | @echo >x509.genkey "[ req ]" | ||
193 | @echo >>x509.genkey "default_bits = 4096" | ||
194 | @echo >>x509.genkey "distinguished_name = req_distinguished_name" | ||
195 | @echo >>x509.genkey "prompt = no" | ||
196 | @echo >>x509.genkey "string_mask = utf8only" | ||
197 | @echo >>x509.genkey "x509_extensions = myexts" | ||
198 | @echo >>x509.genkey | ||
199 | @echo >>x509.genkey "[ req_distinguished_name ]" | ||
200 | @echo >>x509.genkey "O = Magrathea" | ||
201 | @echo >>x509.genkey "CN = Glacier signing key" | ||
202 | @echo >>x509.genkey "emailAddress = slartibartfast@magrathea.h2g2" | ||
203 | @echo >>x509.genkey | ||
204 | @echo >>x509.genkey "[ myexts ]" | ||
205 | @echo >>x509.genkey "basicConstraints=critical,CA:FALSE" | ||
206 | @echo >>x509.genkey "keyUsage=digitalSignature" | ||
207 | @echo >>x509.genkey "subjectKeyIdentifier=hash" | ||
208 | @echo >>x509.genkey "authorityKeyIdentifier=keyid" | ||
209 | endif | ||
diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c new file mode 100644 index 000000000000..4646eb2c3820 --- /dev/null +++ b/kernel/modsign_pubkey.c | |||
@@ -0,0 +1,113 @@ | |||
1 | /* Public keys for module signature verification | ||
2 | * | ||
3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/cred.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <keys/asymmetric-type.h> | ||
17 | #include "module-internal.h" | ||
18 | |||
19 | struct key *modsign_keyring; | ||
20 | |||
21 | extern __initdata const u8 modsign_certificate_list[]; | ||
22 | extern __initdata const u8 modsign_certificate_list_end[]; | ||
23 | asm(".section .init.data,\"aw\"\n" | ||
24 | "modsign_certificate_list:\n" | ||
25 | ".incbin \"signing_key.x509\"\n" | ||
26 | ".incbin \"extra_certificates\"\n" | ||
27 | "modsign_certificate_list_end:" | ||
28 | ); | ||
29 | |||
30 | /* | ||
31 | * We need to make sure ccache doesn't cache the .o file as it doesn't notice | ||
32 | * if modsign.pub changes. | ||
33 | */ | ||
34 | static __initdata const char annoy_ccache[] = __TIME__ "foo"; | ||
35 | |||
36 | /* | ||
37 | * Load the compiled-in keys | ||
38 | */ | ||
39 | static __init int module_verify_init(void) | ||
40 | { | ||
41 | pr_notice("Initialise module verification\n"); | ||
42 | |||
43 | modsign_keyring = key_alloc(&key_type_keyring, ".module_sign", | ||
44 | KUIDT_INIT(0), KGIDT_INIT(0), | ||
45 | current_cred(), | ||
46 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | | ||
47 | KEY_USR_VIEW | KEY_USR_READ, | ||
48 | KEY_ALLOC_NOT_IN_QUOTA); | ||
49 | if (IS_ERR(modsign_keyring)) | ||
50 | panic("Can't allocate module signing keyring\n"); | ||
51 | |||
52 | if (key_instantiate_and_link(modsign_keyring, NULL, 0, NULL, NULL) < 0) | ||
53 | panic("Can't instantiate module signing keyring\n"); | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | /* | ||
59 | * Must be initialised before we try and load the keys into the keyring. | ||
60 | */ | ||
61 | device_initcall(module_verify_init); | ||
62 | |||
63 | /* | ||
64 | * Load the compiled-in keys | ||
65 | */ | ||
66 | static __init int load_module_signing_keys(void) | ||
67 | { | ||
68 | key_ref_t key; | ||
69 | const u8 *p, *end; | ||
70 | size_t plen; | ||
71 | |||
72 | pr_notice("Loading module verification certificates\n"); | ||
73 | |||
74 | end = modsign_certificate_list_end; | ||
75 | p = modsign_certificate_list; | ||
76 | while (p < end) { | ||
77 | /* Each cert begins with an ASN.1 SEQUENCE tag and must be more | ||
78 | * than 256 bytes in size. | ||
79 | */ | ||
80 | if (end - p < 4) | ||
81 | goto dodgy_cert; | ||
82 | if (p[0] != 0x30 && | ||
83 | p[1] != 0x82) | ||
84 | goto dodgy_cert; | ||
85 | plen = (p[2] << 8) | p[3]; | ||
86 | plen += 4; | ||
87 | if (plen > end - p) | ||
88 | goto dodgy_cert; | ||
89 | |||
90 | key = key_create_or_update(make_key_ref(modsign_keyring, 1), | ||
91 | "asymmetric", | ||
92 | NULL, | ||
93 | p, | ||
94 | plen, | ||
95 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | | ||
96 | KEY_USR_VIEW, | ||
97 | KEY_ALLOC_NOT_IN_QUOTA); | ||
98 | if (IS_ERR(key)) | ||
99 | pr_err("MODSIGN: Problem loading in-kernel X.509 certificate (%ld)\n", | ||
100 | PTR_ERR(key)); | ||
101 | else | ||
102 | pr_notice("MODSIGN: Loaded cert '%s'\n", | ||
103 | key_ref_to_ptr(key)->description); | ||
104 | p += plen; | ||
105 | } | ||
106 | |||
107 | return 0; | ||
108 | |||
109 | dodgy_cert: | ||
110 | pr_err("MODSIGN: Problem parsing in-kernel X.509 certificate list\n"); | ||
111 | return 0; | ||
112 | } | ||
113 | late_initcall(load_module_signing_keys); | ||
diff --git a/kernel/module-internal.h b/kernel/module-internal.h new file mode 100644 index 000000000000..6114a13419bd --- /dev/null +++ b/kernel/module-internal.h | |||
@@ -0,0 +1,15 @@ | |||
1 | /* Module internals | ||
2 | * | ||
3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | extern struct key *modsign_keyring; | ||
13 | |||
14 | extern int mod_verify_sig(const void *mod, unsigned long modlen, | ||
15 | const void *sig, unsigned long siglen); | ||
diff --git a/kernel/module.c b/kernel/module.c index 4edbd9c11aca..0e2da8695f8e 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -58,6 +58,8 @@ | |||
58 | #include <linux/jump_label.h> | 58 | #include <linux/jump_label.h> |
59 | #include <linux/pfn.h> | 59 | #include <linux/pfn.h> |
60 | #include <linux/bsearch.h> | 60 | #include <linux/bsearch.h> |
61 | #include <linux/fips.h> | ||
62 | #include "module-internal.h" | ||
61 | 63 | ||
62 | #define CREATE_TRACE_POINTS | 64 | #define CREATE_TRACE_POINTS |
63 | #include <trace/events/module.h> | 65 | #include <trace/events/module.h> |
@@ -102,6 +104,43 @@ static LIST_HEAD(modules); | |||
102 | struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ | 104 | struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */ |
103 | #endif /* CONFIG_KGDB_KDB */ | 105 | #endif /* CONFIG_KGDB_KDB */ |
104 | 106 | ||
107 | #ifdef CONFIG_MODULE_SIG | ||
108 | #ifdef CONFIG_MODULE_SIG_FORCE | ||
109 | static bool sig_enforce = true; | ||
110 | #else | ||
111 | static bool sig_enforce = false; | ||
112 | |||
113 | static int param_set_bool_enable_only(const char *val, | ||
114 | const struct kernel_param *kp) | ||
115 | { | ||
116 | int err; | ||
117 | bool test; | ||
118 | struct kernel_param dummy_kp = *kp; | ||
119 | |||
120 | dummy_kp.arg = &test; | ||
121 | |||
122 | err = param_set_bool(val, &dummy_kp); | ||
123 | if (err) | ||
124 | return err; | ||
125 | |||
126 | /* Don't let them unset it once it's set! */ | ||
127 | if (!test && sig_enforce) | ||
128 | return -EROFS; | ||
129 | |||
130 | if (test) | ||
131 | sig_enforce = true; | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static const struct kernel_param_ops param_ops_bool_enable_only = { | ||
136 | .set = param_set_bool_enable_only, | ||
137 | .get = param_get_bool, | ||
138 | }; | ||
139 | #define param_check_bool_enable_only param_check_bool | ||
140 | |||
141 | module_param(sig_enforce, bool_enable_only, 0644); | ||
142 | #endif /* !CONFIG_MODULE_SIG_FORCE */ | ||
143 | #endif /* CONFIG_MODULE_SIG */ | ||
105 | 144 | ||
106 | /* Block module loading/unloading? */ | 145 | /* Block module loading/unloading? */ |
107 | int modules_disabled = 0; | 146 | int modules_disabled = 0; |
@@ -136,6 +175,7 @@ struct load_info { | |||
136 | unsigned long symoffs, stroffs; | 175 | unsigned long symoffs, stroffs; |
137 | struct _ddebug *debug; | 176 | struct _ddebug *debug; |
138 | unsigned int num_debug; | 177 | unsigned int num_debug; |
178 | bool sig_ok; | ||
139 | struct { | 179 | struct { |
140 | unsigned int sym, str, mod, vers, info, pcpu; | 180 | unsigned int sym, str, mod, vers, info, pcpu; |
141 | } index; | 181 | } index; |
@@ -1949,26 +1989,6 @@ static int simplify_symbols(struct module *mod, const struct load_info *info) | |||
1949 | return ret; | 1989 | return ret; |
1950 | } | 1990 | } |
1951 | 1991 | ||
1952 | int __weak apply_relocate(Elf_Shdr *sechdrs, | ||
1953 | const char *strtab, | ||
1954 | unsigned int symindex, | ||
1955 | unsigned int relsec, | ||
1956 | struct module *me) | ||
1957 | { | ||
1958 | pr_err("module %s: REL relocation unsupported\n", me->name); | ||
1959 | return -ENOEXEC; | ||
1960 | } | ||
1961 | |||
1962 | int __weak apply_relocate_add(Elf_Shdr *sechdrs, | ||
1963 | const char *strtab, | ||
1964 | unsigned int symindex, | ||
1965 | unsigned int relsec, | ||
1966 | struct module *me) | ||
1967 | { | ||
1968 | pr_err("module %s: RELA relocation unsupported\n", me->name); | ||
1969 | return -ENOEXEC; | ||
1970 | } | ||
1971 | |||
1972 | static int apply_relocations(struct module *mod, const struct load_info *info) | 1992 | static int apply_relocations(struct module *mod, const struct load_info *info) |
1973 | { | 1993 | { |
1974 | unsigned int i; | 1994 | unsigned int i; |
@@ -2399,7 +2419,52 @@ static inline void kmemleak_load_module(const struct module *mod, | |||
2399 | } | 2419 | } |
2400 | #endif | 2420 | #endif |
2401 | 2421 | ||
2402 | /* Sets info->hdr and info->len. */ | 2422 | #ifdef CONFIG_MODULE_SIG |
2423 | static int module_sig_check(struct load_info *info, | ||
2424 | const void *mod, unsigned long *len) | ||
2425 | { | ||
2426 | int err = -ENOKEY; | ||
2427 | const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; | ||
2428 | const void *p = mod, *end = mod + *len; | ||
2429 | |||
2430 | /* Poor man's memmem. */ | ||
2431 | while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) { | ||
2432 | if (p + markerlen > end) | ||
2433 | break; | ||
2434 | |||
2435 | if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) { | ||
2436 | const void *sig = p + markerlen; | ||
2437 | /* Truncate module up to signature. */ | ||
2438 | *len = p - mod; | ||
2439 | err = mod_verify_sig(mod, *len, sig, end - sig); | ||
2440 | break; | ||
2441 | } | ||
2442 | p++; | ||
2443 | } | ||
2444 | |||
2445 | if (!err) { | ||
2446 | info->sig_ok = true; | ||
2447 | return 0; | ||
2448 | } | ||
2449 | |||
2450 | /* Not having a signature is only an error if we're strict. */ | ||
2451 | if (err < 0 && fips_enabled) | ||
2452 | panic("Module verification failed with error %d in FIPS mode\n", | ||
2453 | err); | ||
2454 | if (err == -ENOKEY && !sig_enforce) | ||
2455 | err = 0; | ||
2456 | |||
2457 | return err; | ||
2458 | } | ||
2459 | #else /* !CONFIG_MODULE_SIG */ | ||
2460 | static int module_sig_check(struct load_info *info, | ||
2461 | void *mod, unsigned long *len) | ||
2462 | { | ||
2463 | return 0; | ||
2464 | } | ||
2465 | #endif /* !CONFIG_MODULE_SIG */ | ||
2466 | |||
2467 | /* Sets info->hdr, info->len and info->sig_ok. */ | ||
2403 | static int copy_and_check(struct load_info *info, | 2468 | static int copy_and_check(struct load_info *info, |
2404 | const void __user *umod, unsigned long len, | 2469 | const void __user *umod, unsigned long len, |
2405 | const char __user *uargs) | 2470 | const char __user *uargs) |
@@ -2419,6 +2484,10 @@ static int copy_and_check(struct load_info *info, | |||
2419 | goto free_hdr; | 2484 | goto free_hdr; |
2420 | } | 2485 | } |
2421 | 2486 | ||
2487 | err = module_sig_check(info, hdr, &len); | ||
2488 | if (err) | ||
2489 | goto free_hdr; | ||
2490 | |||
2422 | /* Sanity checks against insmoding binaries or wrong arch, | 2491 | /* Sanity checks against insmoding binaries or wrong arch, |
2423 | weird elf version */ | 2492 | weird elf version */ |
2424 | if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0 | 2493 | if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0 |
@@ -2730,6 +2799,10 @@ static int check_module_license_and_versions(struct module *mod) | |||
2730 | if (strcmp(mod->name, "driverloader") == 0) | 2799 | if (strcmp(mod->name, "driverloader") == 0) |
2731 | add_taint_module(mod, TAINT_PROPRIETARY_MODULE); | 2800 | add_taint_module(mod, TAINT_PROPRIETARY_MODULE); |
2732 | 2801 | ||
2802 | /* lve claims to be GPL but upstream won't provide source */ | ||
2803 | if (strcmp(mod->name, "lve") == 0) | ||
2804 | add_taint_module(mod, TAINT_PROPRIETARY_MODULE); | ||
2805 | |||
2733 | #ifdef CONFIG_MODVERSIONS | 2806 | #ifdef CONFIG_MODVERSIONS |
2734 | if ((mod->num_syms && !mod->crcs) | 2807 | if ((mod->num_syms && !mod->crcs) |
2735 | || (mod->num_gpl_syms && !mod->gpl_crcs) | 2808 | || (mod->num_gpl_syms && !mod->gpl_crcs) |
@@ -2861,6 +2934,20 @@ static int post_relocation(struct module *mod, const struct load_info *info) | |||
2861 | return module_finalize(info->hdr, info->sechdrs, mod); | 2934 | return module_finalize(info->hdr, info->sechdrs, mod); |
2862 | } | 2935 | } |
2863 | 2936 | ||
2937 | /* Is this module of this name done loading? No locks held. */ | ||
2938 | static bool finished_loading(const char *name) | ||
2939 | { | ||
2940 | struct module *mod; | ||
2941 | bool ret; | ||
2942 | |||
2943 | mutex_lock(&module_mutex); | ||
2944 | mod = find_module(name); | ||
2945 | ret = !mod || mod->state != MODULE_STATE_COMING; | ||
2946 | mutex_unlock(&module_mutex); | ||
2947 | |||
2948 | return ret; | ||
2949 | } | ||
2950 | |||
2864 | /* Allocate and load the module: note that size of section 0 is always | 2951 | /* Allocate and load the module: note that size of section 0 is always |
2865 | zero, and we rely on this for optional sections. */ | 2952 | zero, and we rely on this for optional sections. */ |
2866 | static struct module *load_module(void __user *umod, | 2953 | static struct module *load_module(void __user *umod, |
@@ -2868,7 +2955,7 @@ static struct module *load_module(void __user *umod, | |||
2868 | const char __user *uargs) | 2955 | const char __user *uargs) |
2869 | { | 2956 | { |
2870 | struct load_info info = { NULL, }; | 2957 | struct load_info info = { NULL, }; |
2871 | struct module *mod; | 2958 | struct module *mod, *old; |
2872 | long err; | 2959 | long err; |
2873 | 2960 | ||
2874 | pr_debug("load_module: umod=%p, len=%lu, uargs=%p\n", | 2961 | pr_debug("load_module: umod=%p, len=%lu, uargs=%p\n", |
@@ -2886,6 +2973,12 @@ static struct module *load_module(void __user *umod, | |||
2886 | goto free_copy; | 2973 | goto free_copy; |
2887 | } | 2974 | } |
2888 | 2975 | ||
2976 | #ifdef CONFIG_MODULE_SIG | ||
2977 | mod->sig_ok = info.sig_ok; | ||
2978 | if (!mod->sig_ok) | ||
2979 | add_taint_module(mod, TAINT_FORCED_MODULE); | ||
2980 | #endif | ||
2981 | |||
2889 | /* Now module is in final location, initialize linked lists, etc. */ | 2982 | /* Now module is in final location, initialize linked lists, etc. */ |
2890 | err = module_unload_init(mod); | 2983 | err = module_unload_init(mod); |
2891 | if (err) | 2984 | if (err) |
@@ -2934,8 +3027,18 @@ static struct module *load_module(void __user *umod, | |||
2934 | * function to insert in a way safe to concurrent readers. | 3027 | * function to insert in a way safe to concurrent readers. |
2935 | * The mutex protects against concurrent writers. | 3028 | * The mutex protects against concurrent writers. |
2936 | */ | 3029 | */ |
3030 | again: | ||
2937 | mutex_lock(&module_mutex); | 3031 | mutex_lock(&module_mutex); |
2938 | if (find_module(mod->name)) { | 3032 | if ((old = find_module(mod->name)) != NULL) { |
3033 | if (old->state == MODULE_STATE_COMING) { | ||
3034 | /* Wait in case it fails to load. */ | ||
3035 | mutex_unlock(&module_mutex); | ||
3036 | err = wait_event_interruptible(module_wq, | ||
3037 | finished_loading(mod->name)); | ||
3038 | if (err) | ||
3039 | goto free_arch_cleanup; | ||
3040 | goto again; | ||
3041 | } | ||
2939 | err = -EEXIST; | 3042 | err = -EEXIST; |
2940 | goto unlock; | 3043 | goto unlock; |
2941 | } | 3044 | } |
@@ -2975,7 +3078,7 @@ static struct module *load_module(void __user *umod, | |||
2975 | /* Unlink carefully: kallsyms could be walking list. */ | 3078 | /* Unlink carefully: kallsyms could be walking list. */ |
2976 | list_del_rcu(&mod->list); | 3079 | list_del_rcu(&mod->list); |
2977 | module_bug_cleanup(mod); | 3080 | module_bug_cleanup(mod); |
2978 | 3081 | wake_up_all(&module_wq); | |
2979 | ddebug: | 3082 | ddebug: |
2980 | dynamic_debug_remove(info.debug); | 3083 | dynamic_debug_remove(info.debug); |
2981 | unlock: | 3084 | unlock: |
@@ -3050,7 +3153,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, | |||
3050 | blocking_notifier_call_chain(&module_notify_list, | 3153 | blocking_notifier_call_chain(&module_notify_list, |
3051 | MODULE_STATE_GOING, mod); | 3154 | MODULE_STATE_GOING, mod); |
3052 | free_module(mod); | 3155 | free_module(mod); |
3053 | wake_up(&module_wq); | 3156 | wake_up_all(&module_wq); |
3054 | return ret; | 3157 | return ret; |
3055 | } | 3158 | } |
3056 | if (ret > 0) { | 3159 | if (ret > 0) { |
@@ -3062,9 +3165,8 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, | |||
3062 | dump_stack(); | 3165 | dump_stack(); |
3063 | } | 3166 | } |
3064 | 3167 | ||
3065 | /* Now it's a first class citizen! Wake up anyone waiting for it. */ | 3168 | /* Now it's a first class citizen! */ |
3066 | mod->state = MODULE_STATE_LIVE; | 3169 | mod->state = MODULE_STATE_LIVE; |
3067 | wake_up(&module_wq); | ||
3068 | blocking_notifier_call_chain(&module_notify_list, | 3170 | blocking_notifier_call_chain(&module_notify_list, |
3069 | MODULE_STATE_LIVE, mod); | 3171 | MODULE_STATE_LIVE, mod); |
3070 | 3172 | ||
@@ -3087,6 +3189,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, | |||
3087 | mod->init_ro_size = 0; | 3189 | mod->init_ro_size = 0; |
3088 | mod->init_text_size = 0; | 3190 | mod->init_text_size = 0; |
3089 | mutex_unlock(&module_mutex); | 3191 | mutex_unlock(&module_mutex); |
3192 | wake_up_all(&module_wq); | ||
3090 | 3193 | ||
3091 | return 0; | 3194 | return 0; |
3092 | } | 3195 | } |
diff --git a/kernel/module_signing.c b/kernel/module_signing.c new file mode 100644 index 000000000000..6b09f6983ac0 --- /dev/null +++ b/kernel/module_signing.c | |||
@@ -0,0 +1,243 @@ | |||
1 | /* Module signature checker | ||
2 | * | ||
3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/err.h> | ||
14 | #include <crypto/public_key.h> | ||
15 | #include <crypto/hash.h> | ||
16 | #include <keys/asymmetric-type.h> | ||
17 | #include "module-internal.h" | ||
18 | |||
19 | /* | ||
20 | * Module signature information block. | ||
21 | * | ||
22 | * The constituents of the signature section are, in order: | ||
23 | * | ||
24 | * - Signer's name | ||
25 | * - Key identifier | ||
26 | * - Signature data | ||
27 | * - Information block | ||
28 | */ | ||
29 | struct module_signature { | ||
30 | enum pkey_algo algo : 8; /* Public-key crypto algorithm */ | ||
31 | enum pkey_hash_algo hash : 8; /* Digest algorithm */ | ||
32 | enum pkey_id_type id_type : 8; /* Key identifier type */ | ||
33 | u8 signer_len; /* Length of signer's name */ | ||
34 | u8 key_id_len; /* Length of key identifier */ | ||
35 | u8 __pad[3]; | ||
36 | __be32 sig_len; /* Length of signature data */ | ||
37 | }; | ||
38 | |||
39 | /* | ||
40 | * Digest the module contents. | ||
41 | */ | ||
42 | static struct public_key_signature *mod_make_digest(enum pkey_hash_algo hash, | ||
43 | const void *mod, | ||
44 | unsigned long modlen) | ||
45 | { | ||
46 | struct public_key_signature *pks; | ||
47 | struct crypto_shash *tfm; | ||
48 | struct shash_desc *desc; | ||
49 | size_t digest_size, desc_size; | ||
50 | int ret; | ||
51 | |||
52 | pr_devel("==>%s()\n", __func__); | ||
53 | |||
54 | /* Allocate the hashing algorithm we're going to need and find out how | ||
55 | * big the hash operational data will be. | ||
56 | */ | ||
57 | tfm = crypto_alloc_shash(pkey_hash_algo[hash], 0, 0); | ||
58 | if (IS_ERR(tfm)) | ||
59 | return (PTR_ERR(tfm) == -ENOENT) ? ERR_PTR(-ENOPKG) : ERR_CAST(tfm); | ||
60 | |||
61 | desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); | ||
62 | digest_size = crypto_shash_digestsize(tfm); | ||
63 | |||
64 | /* We allocate the hash operational data storage on the end of our | ||
65 | * context data and the digest output buffer on the end of that. | ||
66 | */ | ||
67 | ret = -ENOMEM; | ||
68 | pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL); | ||
69 | if (!pks) | ||
70 | goto error_no_pks; | ||
71 | |||
72 | pks->pkey_hash_algo = hash; | ||
73 | pks->digest = (u8 *)pks + sizeof(*pks) + desc_size; | ||
74 | pks->digest_size = digest_size; | ||
75 | |||
76 | desc = (void *)pks + sizeof(*pks); | ||
77 | desc->tfm = tfm; | ||
78 | desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; | ||
79 | |||
80 | ret = crypto_shash_init(desc); | ||
81 | if (ret < 0) | ||
82 | goto error; | ||
83 | |||
84 | ret = crypto_shash_finup(desc, mod, modlen, pks->digest); | ||
85 | if (ret < 0) | ||
86 | goto error; | ||
87 | |||
88 | crypto_free_shash(tfm); | ||
89 | pr_devel("<==%s() = ok\n", __func__); | ||
90 | return pks; | ||
91 | |||
92 | error: | ||
93 | kfree(pks); | ||
94 | error_no_pks: | ||
95 | crypto_free_shash(tfm); | ||
96 | pr_devel("<==%s() = %d\n", __func__, ret); | ||
97 | return ERR_PTR(ret); | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * Extract an MPI array from the signature data. This represents the actual | ||
102 | * signature. Each raw MPI is prefaced by a BE 2-byte value indicating the | ||
103 | * size of the MPI in bytes. | ||
104 | * | ||
105 | * RSA signatures only have one MPI, so currently we only read one. | ||
106 | */ | ||
107 | static int mod_extract_mpi_array(struct public_key_signature *pks, | ||
108 | const void *data, size_t len) | ||
109 | { | ||
110 | size_t nbytes; | ||
111 | MPI mpi; | ||
112 | |||
113 | if (len < 3) | ||
114 | return -EBADMSG; | ||
115 | nbytes = ((const u8 *)data)[0] << 8 | ((const u8 *)data)[1]; | ||
116 | data += 2; | ||
117 | len -= 2; | ||
118 | if (len != nbytes) | ||
119 | return -EBADMSG; | ||
120 | |||
121 | mpi = mpi_read_raw_data(data, nbytes); | ||
122 | if (!mpi) | ||
123 | return -ENOMEM; | ||
124 | pks->mpi[0] = mpi; | ||
125 | pks->nr_mpi = 1; | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | * Request an asymmetric key. | ||
131 | */ | ||
132 | static struct key *request_asymmetric_key(const char *signer, size_t signer_len, | ||
133 | const u8 *key_id, size_t key_id_len) | ||
134 | { | ||
135 | key_ref_t key; | ||
136 | size_t i; | ||
137 | char *id, *q; | ||
138 | |||
139 | pr_devel("==>%s(,%zu,,%zu)\n", __func__, signer_len, key_id_len); | ||
140 | |||
141 | /* Construct an identifier. */ | ||
142 | id = kmalloc(signer_len + 2 + key_id_len * 2 + 1, GFP_KERNEL); | ||
143 | if (!id) | ||
144 | return ERR_PTR(-ENOKEY); | ||
145 | |||
146 | memcpy(id, signer, signer_len); | ||
147 | |||
148 | q = id + signer_len; | ||
149 | *q++ = ':'; | ||
150 | *q++ = ' '; | ||
151 | for (i = 0; i < key_id_len; i++) { | ||
152 | *q++ = hex_asc[*key_id >> 4]; | ||
153 | *q++ = hex_asc[*key_id++ & 0x0f]; | ||
154 | } | ||
155 | |||
156 | *q = 0; | ||
157 | |||
158 | pr_debug("Look up: \"%s\"\n", id); | ||
159 | |||
160 | key = keyring_search(make_key_ref(modsign_keyring, 1), | ||
161 | &key_type_asymmetric, id); | ||
162 | if (IS_ERR(key)) | ||
163 | pr_warn("Request for unknown module key '%s' err %ld\n", | ||
164 | id, PTR_ERR(key)); | ||
165 | kfree(id); | ||
166 | |||
167 | if (IS_ERR(key)) { | ||
168 | switch (PTR_ERR(key)) { | ||
169 | /* Hide some search errors */ | ||
170 | case -EACCES: | ||
171 | case -ENOTDIR: | ||
172 | case -EAGAIN: | ||
173 | return ERR_PTR(-ENOKEY); | ||
174 | default: | ||
175 | return ERR_CAST(key); | ||
176 | } | ||
177 | } | ||
178 | |||
179 | pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key))); | ||
180 | return key_ref_to_ptr(key); | ||
181 | } | ||
182 | |||
183 | /* | ||
184 | * Verify the signature on a module. | ||
185 | */ | ||
186 | int mod_verify_sig(const void *mod, unsigned long modlen, | ||
187 | const void *sig, unsigned long siglen) | ||
188 | { | ||
189 | struct public_key_signature *pks; | ||
190 | struct module_signature ms; | ||
191 | struct key *key; | ||
192 | size_t sig_len; | ||
193 | int ret; | ||
194 | |||
195 | pr_devel("==>%s(,%lu,,%lu,)\n", __func__, modlen, siglen); | ||
196 | |||
197 | if (siglen <= sizeof(ms)) | ||
198 | return -EBADMSG; | ||
199 | |||
200 | memcpy(&ms, sig + (siglen - sizeof(ms)), sizeof(ms)); | ||
201 | siglen -= sizeof(ms); | ||
202 | |||
203 | sig_len = be32_to_cpu(ms.sig_len); | ||
204 | if (sig_len >= siglen || | ||
205 | siglen - sig_len != (size_t)ms.signer_len + ms.key_id_len) | ||
206 | return -EBADMSG; | ||
207 | |||
208 | /* For the moment, only support RSA and X.509 identifiers */ | ||
209 | if (ms.algo != PKEY_ALGO_RSA || | ||
210 | ms.id_type != PKEY_ID_X509) | ||
211 | return -ENOPKG; | ||
212 | |||
213 | if (ms.hash >= PKEY_HASH__LAST || | ||
214 | !pkey_hash_algo[ms.hash]) | ||
215 | return -ENOPKG; | ||
216 | |||
217 | key = request_asymmetric_key(sig, ms.signer_len, | ||
218 | sig + ms.signer_len, ms.key_id_len); | ||
219 | if (IS_ERR(key)) | ||
220 | return PTR_ERR(key); | ||
221 | |||
222 | pks = mod_make_digest(ms.hash, mod, modlen); | ||
223 | if (IS_ERR(pks)) { | ||
224 | ret = PTR_ERR(pks); | ||
225 | goto error_put_key; | ||
226 | } | ||
227 | |||
228 | ret = mod_extract_mpi_array(pks, sig + ms.signer_len + ms.key_id_len, | ||
229 | sig_len); | ||
230 | if (ret < 0) | ||
231 | goto error_free_pks; | ||
232 | |||
233 | ret = verify_signature(key, pks); | ||
234 | pr_devel("verify_signature() = %d\n", ret); | ||
235 | |||
236 | error_free_pks: | ||
237 | mpi_free(pks->rsa.s); | ||
238 | kfree(pks); | ||
239 | error_put_key: | ||
240 | key_put(key); | ||
241 | pr_devel("<==%s() = %d\n", __func__, ret); | ||
242 | return ret; | ||
243 | } | ||
diff --git a/lib/.gitignore b/lib/.gitignore index 3bef1ea94c99..09aae85418ab 100644 --- a/lib/.gitignore +++ b/lib/.gitignore | |||
@@ -3,4 +3,4 @@ | |||
3 | # | 3 | # |
4 | gen_crc32table | 4 | gen_crc32table |
5 | crc32table.h | 5 | crc32table.h |
6 | 6 | oid_registry_data.c | |
diff --git a/lib/Kconfig b/lib/Kconfig index bb94c1ba616a..4b31a46fb307 100644 --- a/lib/Kconfig +++ b/lib/Kconfig | |||
@@ -396,4 +396,9 @@ config SIGNATURE | |||
396 | config LIBFDT | 396 | config LIBFDT |
397 | bool | 397 | bool |
398 | 398 | ||
399 | config OID_REGISTRY | ||
400 | tristate | ||
401 | help | ||
402 | Enable fast lookup object identifier registry. | ||
403 | |||
399 | endmenu | 404 | endmenu |
diff --git a/lib/Makefile b/lib/Makefile index 3128e357e286..821a16229111 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
@@ -145,6 +145,8 @@ obj-$(CONFIG_INTERVAL_TREE_TEST) += interval_tree_test.o | |||
145 | 145 | ||
146 | interval_tree_test-objs := interval_tree_test_main.o interval_tree.o | 146 | interval_tree_test-objs := interval_tree_test_main.o interval_tree.o |
147 | 147 | ||
148 | obj-$(CONFIG_ASN1) += asn1_decoder.o | ||
149 | |||
148 | hostprogs-y := gen_crc32table | 150 | hostprogs-y := gen_crc32table |
149 | clean-files := crc32table.h | 151 | clean-files := crc32table.h |
150 | 152 | ||
@@ -155,3 +157,19 @@ quiet_cmd_crc32 = GEN $@ | |||
155 | 157 | ||
156 | $(obj)/crc32table.h: $(obj)/gen_crc32table | 158 | $(obj)/crc32table.h: $(obj)/gen_crc32table |
157 | $(call cmd,crc32) | 159 | $(call cmd,crc32) |
160 | |||
161 | # | ||
162 | # Build a fast OID lookip registry from include/linux/oid_registry.h | ||
163 | # | ||
164 | obj-$(CONFIG_OID_REGISTRY) += oid_registry.o | ||
165 | |||
166 | $(obj)/oid_registry.c: $(obj)/oid_registry_data.c | ||
167 | |||
168 | $(obj)/oid_registry_data.c: $(srctree)/include/linux/oid_registry.h \ | ||
169 | $(src)/build_OID_registry | ||
170 | $(call cmd,build_OID_registry) | ||
171 | |||
172 | quiet_cmd_build_OID_registry = GEN $@ | ||
173 | cmd_build_OID_registry = perl $(srctree)/$(src)/build_OID_registry $< $@ | ||
174 | |||
175 | clean-files += oid_registry_data.c | ||
diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c new file mode 100644 index 000000000000..de2c8b5a715b --- /dev/null +++ b/lib/asn1_decoder.c | |||
@@ -0,0 +1,487 @@ | |||
1 | /* Decoder for ASN.1 BER/DER/CER encoded bytestream | ||
2 | * | ||
3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/export.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/asn1_decoder.h> | ||
16 | #include <linux/asn1_ber_bytecode.h> | ||
17 | |||
18 | static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { | ||
19 | /* OPC TAG JMP ACT */ | ||
20 | [ASN1_OP_MATCH] = 1 + 1, | ||
21 | [ASN1_OP_MATCH_OR_SKIP] = 1 + 1, | ||
22 | [ASN1_OP_MATCH_ACT] = 1 + 1 + 1, | ||
23 | [ASN1_OP_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, | ||
24 | [ASN1_OP_MATCH_JUMP] = 1 + 1 + 1, | ||
25 | [ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, | ||
26 | [ASN1_OP_MATCH_ANY] = 1, | ||
27 | [ASN1_OP_MATCH_ANY_ACT] = 1 + 1, | ||
28 | [ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1, | ||
29 | [ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1, | ||
30 | [ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1, | ||
31 | [ASN1_OP_COND_MATCH_ANY] = 1, | ||
32 | [ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1, | ||
33 | [ASN1_OP_COND_FAIL] = 1, | ||
34 | [ASN1_OP_COMPLETE] = 1, | ||
35 | [ASN1_OP_ACT] = 1 + 1, | ||
36 | [ASN1_OP_RETURN] = 1, | ||
37 | [ASN1_OP_END_SEQ] = 1, | ||
38 | [ASN1_OP_END_SEQ_OF] = 1 + 1, | ||
39 | [ASN1_OP_END_SET] = 1, | ||
40 | [ASN1_OP_END_SET_OF] = 1 + 1, | ||
41 | [ASN1_OP_END_SEQ_ACT] = 1 + 1, | ||
42 | [ASN1_OP_END_SEQ_OF_ACT] = 1 + 1 + 1, | ||
43 | [ASN1_OP_END_SET_ACT] = 1 + 1, | ||
44 | [ASN1_OP_END_SET_OF_ACT] = 1 + 1 + 1, | ||
45 | }; | ||
46 | |||
47 | /* | ||
48 | * Find the length of an indefinite length object | ||
49 | * @data: The data buffer | ||
50 | * @datalen: The end of the innermost containing element in the buffer | ||
51 | * @_dp: The data parse cursor (updated before returning) | ||
52 | * @_len: Where to return the size of the element. | ||
53 | * @_errmsg: Where to return a pointer to an error message on error | ||
54 | */ | ||
55 | static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen, | ||
56 | size_t *_dp, size_t *_len, | ||
57 | const char **_errmsg) | ||
58 | { | ||
59 | unsigned char tag, tmp; | ||
60 | size_t dp = *_dp, len, n; | ||
61 | int indef_level = 1; | ||
62 | |||
63 | next_tag: | ||
64 | if (unlikely(datalen - dp < 2)) { | ||
65 | if (datalen == dp) | ||
66 | goto missing_eoc; | ||
67 | goto data_overrun_error; | ||
68 | } | ||
69 | |||
70 | /* Extract a tag from the data */ | ||
71 | tag = data[dp++]; | ||
72 | if (tag == 0) { | ||
73 | /* It appears to be an EOC. */ | ||
74 | if (data[dp++] != 0) | ||
75 | goto invalid_eoc; | ||
76 | if (--indef_level <= 0) { | ||
77 | *_len = dp - *_dp; | ||
78 | *_dp = dp; | ||
79 | return 0; | ||
80 | } | ||
81 | goto next_tag; | ||
82 | } | ||
83 | |||
84 | if (unlikely((tag & 0x1f) == 0x1f)) { | ||
85 | do { | ||
86 | if (unlikely(datalen - dp < 2)) | ||
87 | goto data_overrun_error; | ||
88 | tmp = data[dp++]; | ||
89 | } while (tmp & 0x80); | ||
90 | } | ||
91 | |||
92 | /* Extract the length */ | ||
93 | len = data[dp++]; | ||
94 | if (len < 0x7f) { | ||
95 | dp += len; | ||
96 | goto next_tag; | ||
97 | } | ||
98 | |||
99 | if (unlikely(len == 0x80)) { | ||
100 | /* Indefinite length */ | ||
101 | if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5)) | ||
102 | goto indefinite_len_primitive; | ||
103 | indef_level++; | ||
104 | goto next_tag; | ||
105 | } | ||
106 | |||
107 | n = len - 0x80; | ||
108 | if (unlikely(n > sizeof(size_t) - 1)) | ||
109 | goto length_too_long; | ||
110 | if (unlikely(n > datalen - dp)) | ||
111 | goto data_overrun_error; | ||
112 | for (len = 0; n > 0; n--) { | ||
113 | len <<= 8; | ||
114 | len |= data[dp++]; | ||
115 | } | ||
116 | dp += len; | ||
117 | goto next_tag; | ||
118 | |||
119 | length_too_long: | ||
120 | *_errmsg = "Unsupported length"; | ||
121 | goto error; | ||
122 | indefinite_len_primitive: | ||
123 | *_errmsg = "Indefinite len primitive not permitted"; | ||
124 | goto error; | ||
125 | invalid_eoc: | ||
126 | *_errmsg = "Invalid length EOC"; | ||
127 | goto error; | ||
128 | data_overrun_error: | ||
129 | *_errmsg = "Data overrun error"; | ||
130 | goto error; | ||
131 | missing_eoc: | ||
132 | *_errmsg = "Missing EOC in indefinite len cons"; | ||
133 | error: | ||
134 | *_dp = dp; | ||
135 | return -1; | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * asn1_ber_decoder - Decoder BER/DER/CER ASN.1 according to pattern | ||
140 | * @decoder: The decoder definition (produced by asn1_compiler) | ||
141 | * @context: The caller's context (to be passed to the action functions) | ||
142 | * @data: The encoded data | ||
143 | * @datasize: The size of the encoded data | ||
144 | * | ||
145 | * Decode BER/DER/CER encoded ASN.1 data according to a bytecode pattern | ||
146 | * produced by asn1_compiler. Action functions are called on marked tags to | ||
147 | * allow the caller to retrieve significant data. | ||
148 | * | ||
149 | * LIMITATIONS: | ||
150 | * | ||
151 | * To keep down the amount of stack used by this function, the following limits | ||
152 | * have been imposed: | ||
153 | * | ||
154 | * (1) This won't handle datalen > 65535 without increasing the size of the | ||
155 | * cons stack elements and length_too_long checking. | ||
156 | * | ||
157 | * (2) The stack of constructed types is 10 deep. If the depth of non-leaf | ||
158 | * constructed types exceeds this, the decode will fail. | ||
159 | * | ||
160 | * (3) The SET type (not the SET OF type) isn't really supported as tracking | ||
161 | * what members of the set have been seen is a pain. | ||
162 | */ | ||
163 | int asn1_ber_decoder(const struct asn1_decoder *decoder, | ||
164 | void *context, | ||
165 | const unsigned char *data, | ||
166 | size_t datalen) | ||
167 | { | ||
168 | const unsigned char *machine = decoder->machine; | ||
169 | const asn1_action_t *actions = decoder->actions; | ||
170 | size_t machlen = decoder->machlen; | ||
171 | enum asn1_opcode op; | ||
172 | unsigned char tag = 0, csp = 0, jsp = 0, optag = 0, hdr = 0; | ||
173 | const char *errmsg; | ||
174 | size_t pc = 0, dp = 0, tdp = 0, len = 0; | ||
175 | int ret; | ||
176 | |||
177 | unsigned char flags = 0; | ||
178 | #define FLAG_INDEFINITE_LENGTH 0x01 | ||
179 | #define FLAG_MATCHED 0x02 | ||
180 | #define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag | ||
181 | * - ie. whether or not we are going to parse | ||
182 | * a compound type. | ||
183 | */ | ||
184 | |||
185 | #define NR_CONS_STACK 10 | ||
186 | unsigned short cons_dp_stack[NR_CONS_STACK]; | ||
187 | unsigned short cons_datalen_stack[NR_CONS_STACK]; | ||
188 | unsigned char cons_hdrlen_stack[NR_CONS_STACK]; | ||
189 | #define NR_JUMP_STACK 10 | ||
190 | unsigned char jump_stack[NR_JUMP_STACK]; | ||
191 | |||
192 | if (datalen > 65535) | ||
193 | return -EMSGSIZE; | ||
194 | |||
195 | next_op: | ||
196 | pr_debug("next_op: pc=\e[32m%zu\e[m/%zu dp=\e[33m%zu\e[m/%zu C=%d J=%d\n", | ||
197 | pc, machlen, dp, datalen, csp, jsp); | ||
198 | if (unlikely(pc >= machlen)) | ||
199 | goto machine_overrun_error; | ||
200 | op = machine[pc]; | ||
201 | if (unlikely(pc + asn1_op_lengths[op] > machlen)) | ||
202 | goto machine_overrun_error; | ||
203 | |||
204 | /* If this command is meant to match a tag, then do that before | ||
205 | * evaluating the command. | ||
206 | */ | ||
207 | if (op <= ASN1_OP__MATCHES_TAG) { | ||
208 | unsigned char tmp; | ||
209 | |||
210 | /* Skip conditional matches if possible */ | ||
211 | if ((op & ASN1_OP_MATCH__COND && | ||
212 | flags & FLAG_MATCHED) || | ||
213 | dp == datalen) { | ||
214 | pc += asn1_op_lengths[op]; | ||
215 | goto next_op; | ||
216 | } | ||
217 | |||
218 | flags = 0; | ||
219 | hdr = 2; | ||
220 | |||
221 | /* Extract a tag from the data */ | ||
222 | if (unlikely(dp >= datalen - 1)) | ||
223 | goto data_overrun_error; | ||
224 | tag = data[dp++]; | ||
225 | if (unlikely((tag & 0x1f) == 0x1f)) | ||
226 | goto long_tag_not_supported; | ||
227 | |||
228 | if (op & ASN1_OP_MATCH__ANY) { | ||
229 | pr_debug("- any %02x\n", tag); | ||
230 | } else { | ||
231 | /* Extract the tag from the machine | ||
232 | * - Either CONS or PRIM are permitted in the data if | ||
233 | * CONS is not set in the op stream, otherwise CONS | ||
234 | * is mandatory. | ||
235 | */ | ||
236 | optag = machine[pc + 1]; | ||
237 | flags |= optag & FLAG_CONS; | ||
238 | |||
239 | /* Determine whether the tag matched */ | ||
240 | tmp = optag ^ tag; | ||
241 | tmp &= ~(optag & ASN1_CONS_BIT); | ||
242 | pr_debug("- match? %02x %02x %02x\n", tag, optag, tmp); | ||
243 | if (tmp != 0) { | ||
244 | /* All odd-numbered tags are MATCH_OR_SKIP. */ | ||
245 | if (op & ASN1_OP_MATCH__SKIP) { | ||
246 | pc += asn1_op_lengths[op]; | ||
247 | dp--; | ||
248 | goto next_op; | ||
249 | } | ||
250 | goto tag_mismatch; | ||
251 | } | ||
252 | } | ||
253 | flags |= FLAG_MATCHED; | ||
254 | |||
255 | len = data[dp++]; | ||
256 | if (len > 0x7f) { | ||
257 | if (unlikely(len == 0x80)) { | ||
258 | /* Indefinite length */ | ||
259 | if (unlikely(!(tag & ASN1_CONS_BIT))) | ||
260 | goto indefinite_len_primitive; | ||
261 | flags |= FLAG_INDEFINITE_LENGTH; | ||
262 | if (unlikely(2 > datalen - dp)) | ||
263 | goto data_overrun_error; | ||
264 | } else { | ||
265 | int n = len - 0x80; | ||
266 | if (unlikely(n > 2)) | ||
267 | goto length_too_long; | ||
268 | if (unlikely(dp >= datalen - n)) | ||
269 | goto data_overrun_error; | ||
270 | hdr += n; | ||
271 | for (len = 0; n > 0; n--) { | ||
272 | len <<= 8; | ||
273 | len |= data[dp++]; | ||
274 | } | ||
275 | if (unlikely(len > datalen - dp)) | ||
276 | goto data_overrun_error; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | if (flags & FLAG_CONS) { | ||
281 | /* For expected compound forms, we stack the positions | ||
282 | * of the start and end of the data. | ||
283 | */ | ||
284 | if (unlikely(csp >= NR_CONS_STACK)) | ||
285 | goto cons_stack_overflow; | ||
286 | cons_dp_stack[csp] = dp; | ||
287 | cons_hdrlen_stack[csp] = hdr; | ||
288 | if (!(flags & FLAG_INDEFINITE_LENGTH)) { | ||
289 | cons_datalen_stack[csp] = datalen; | ||
290 | datalen = dp + len; | ||
291 | } else { | ||
292 | cons_datalen_stack[csp] = 0; | ||
293 | } | ||
294 | csp++; | ||
295 | } | ||
296 | |||
297 | pr_debug("- TAG: %02x %zu%s\n", | ||
298 | tag, len, flags & FLAG_CONS ? " CONS" : ""); | ||
299 | tdp = dp; | ||
300 | } | ||
301 | |||
302 | /* Decide how to handle the operation */ | ||
303 | switch (op) { | ||
304 | case ASN1_OP_MATCH_ANY_ACT: | ||
305 | case ASN1_OP_COND_MATCH_ANY_ACT: | ||
306 | ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len); | ||
307 | if (ret < 0) | ||
308 | return ret; | ||
309 | goto skip_data; | ||
310 | |||
311 | case ASN1_OP_MATCH_ACT: | ||
312 | case ASN1_OP_MATCH_ACT_OR_SKIP: | ||
313 | case ASN1_OP_COND_MATCH_ACT_OR_SKIP: | ||
314 | ret = actions[machine[pc + 2]](context, hdr, tag, data + dp, len); | ||
315 | if (ret < 0) | ||
316 | return ret; | ||
317 | goto skip_data; | ||
318 | |||
319 | case ASN1_OP_MATCH: | ||
320 | case ASN1_OP_MATCH_OR_SKIP: | ||
321 | case ASN1_OP_MATCH_ANY: | ||
322 | case ASN1_OP_COND_MATCH_OR_SKIP: | ||
323 | case ASN1_OP_COND_MATCH_ANY: | ||
324 | skip_data: | ||
325 | if (!(flags & FLAG_CONS)) { | ||
326 | if (flags & FLAG_INDEFINITE_LENGTH) { | ||
327 | ret = asn1_find_indefinite_length( | ||
328 | data, datalen, &dp, &len, &errmsg); | ||
329 | if (ret < 0) | ||
330 | goto error; | ||
331 | } else { | ||
332 | dp += len; | ||
333 | } | ||
334 | pr_debug("- LEAF: %zu\n", len); | ||
335 | } | ||
336 | pc += asn1_op_lengths[op]; | ||
337 | goto next_op; | ||
338 | |||
339 | case ASN1_OP_MATCH_JUMP: | ||
340 | case ASN1_OP_MATCH_JUMP_OR_SKIP: | ||
341 | case ASN1_OP_COND_MATCH_JUMP_OR_SKIP: | ||
342 | pr_debug("- MATCH_JUMP\n"); | ||
343 | if (unlikely(jsp == NR_JUMP_STACK)) | ||
344 | goto jump_stack_overflow; | ||
345 | jump_stack[jsp++] = pc + asn1_op_lengths[op]; | ||
346 | pc = machine[pc + 2]; | ||
347 | goto next_op; | ||
348 | |||
349 | case ASN1_OP_COND_FAIL: | ||
350 | if (unlikely(!(flags & FLAG_MATCHED))) | ||
351 | goto tag_mismatch; | ||
352 | pc += asn1_op_lengths[op]; | ||
353 | goto next_op; | ||
354 | |||
355 | case ASN1_OP_COMPLETE: | ||
356 | if (unlikely(jsp != 0 || csp != 0)) { | ||
357 | pr_err("ASN.1 decoder error: Stacks not empty at completion (%u, %u)\n", | ||
358 | jsp, csp); | ||
359 | return -EBADMSG; | ||
360 | } | ||
361 | return 0; | ||
362 | |||
363 | case ASN1_OP_END_SET: | ||
364 | case ASN1_OP_END_SET_ACT: | ||
365 | if (unlikely(!(flags & FLAG_MATCHED))) | ||
366 | goto tag_mismatch; | ||
367 | case ASN1_OP_END_SEQ: | ||
368 | case ASN1_OP_END_SET_OF: | ||
369 | case ASN1_OP_END_SEQ_OF: | ||
370 | case ASN1_OP_END_SEQ_ACT: | ||
371 | case ASN1_OP_END_SET_OF_ACT: | ||
372 | case ASN1_OP_END_SEQ_OF_ACT: | ||
373 | if (unlikely(csp <= 0)) | ||
374 | goto cons_stack_underflow; | ||
375 | csp--; | ||
376 | tdp = cons_dp_stack[csp]; | ||
377 | hdr = cons_hdrlen_stack[csp]; | ||
378 | len = datalen; | ||
379 | datalen = cons_datalen_stack[csp]; | ||
380 | pr_debug("- end cons t=%zu dp=%zu l=%zu/%zu\n", | ||
381 | tdp, dp, len, datalen); | ||
382 | if (datalen == 0) { | ||
383 | /* Indefinite length - check for the EOC. */ | ||
384 | datalen = len; | ||
385 | if (unlikely(datalen - dp < 2)) | ||
386 | goto data_overrun_error; | ||
387 | if (data[dp++] != 0) { | ||
388 | if (op & ASN1_OP_END__OF) { | ||
389 | dp--; | ||
390 | csp++; | ||
391 | pc = machine[pc + 1]; | ||
392 | pr_debug("- continue\n"); | ||
393 | goto next_op; | ||
394 | } | ||
395 | goto missing_eoc; | ||
396 | } | ||
397 | if (data[dp++] != 0) | ||
398 | goto invalid_eoc; | ||
399 | len = dp - tdp - 2; | ||
400 | } else { | ||
401 | if (dp < len && (op & ASN1_OP_END__OF)) { | ||
402 | datalen = len; | ||
403 | csp++; | ||
404 | pc = machine[pc + 1]; | ||
405 | pr_debug("- continue\n"); | ||
406 | goto next_op; | ||
407 | } | ||
408 | if (dp != len) | ||
409 | goto cons_length_error; | ||
410 | len -= tdp; | ||
411 | pr_debug("- cons len l=%zu d=%zu\n", len, dp - tdp); | ||
412 | } | ||
413 | |||
414 | if (op & ASN1_OP_END__ACT) { | ||
415 | unsigned char act; | ||
416 | if (op & ASN1_OP_END__OF) | ||
417 | act = machine[pc + 2]; | ||
418 | else | ||
419 | act = machine[pc + 1]; | ||
420 | ret = actions[act](context, hdr, 0, data + tdp, len); | ||
421 | } | ||
422 | pc += asn1_op_lengths[op]; | ||
423 | goto next_op; | ||
424 | |||
425 | case ASN1_OP_ACT: | ||
426 | ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len); | ||
427 | pc += asn1_op_lengths[op]; | ||
428 | goto next_op; | ||
429 | |||
430 | case ASN1_OP_RETURN: | ||
431 | if (unlikely(jsp <= 0)) | ||
432 | goto jump_stack_underflow; | ||
433 | pc = jump_stack[--jsp]; | ||
434 | goto next_op; | ||
435 | |||
436 | default: | ||
437 | break; | ||
438 | } | ||
439 | |||
440 | /* Shouldn't reach here */ | ||
441 | pr_err("ASN.1 decoder error: Found reserved opcode (%u)\n", op); | ||
442 | return -EBADMSG; | ||
443 | |||
444 | data_overrun_error: | ||
445 | errmsg = "Data overrun error"; | ||
446 | goto error; | ||
447 | machine_overrun_error: | ||
448 | errmsg = "Machine overrun error"; | ||
449 | goto error; | ||
450 | jump_stack_underflow: | ||
451 | errmsg = "Jump stack underflow"; | ||
452 | goto error; | ||
453 | jump_stack_overflow: | ||
454 | errmsg = "Jump stack overflow"; | ||
455 | goto error; | ||
456 | cons_stack_underflow: | ||
457 | errmsg = "Cons stack underflow"; | ||
458 | goto error; | ||
459 | cons_stack_overflow: | ||
460 | errmsg = "Cons stack overflow"; | ||
461 | goto error; | ||
462 | cons_length_error: | ||
463 | errmsg = "Cons length error"; | ||
464 | goto error; | ||
465 | missing_eoc: | ||
466 | errmsg = "Missing EOC in indefinite len cons"; | ||
467 | goto error; | ||
468 | invalid_eoc: | ||
469 | errmsg = "Invalid length EOC"; | ||
470 | goto error; | ||
471 | length_too_long: | ||
472 | errmsg = "Unsupported length"; | ||
473 | goto error; | ||
474 | indefinite_len_primitive: | ||
475 | errmsg = "Indefinite len primitive not permitted"; | ||
476 | goto error; | ||
477 | tag_mismatch: | ||
478 | errmsg = "Unexpected tag"; | ||
479 | goto error; | ||
480 | long_tag_not_supported: | ||
481 | errmsg = "Long tag not supported"; | ||
482 | error: | ||
483 | pr_debug("\nASN1: %s [m=%zu d=%zu ot=%02x t=%02x l=%zu]\n", | ||
484 | errmsg, pc, dp, optag, tag, len); | ||
485 | return -EBADMSG; | ||
486 | } | ||
487 | EXPORT_SYMBOL_GPL(asn1_ber_decoder); | ||
diff --git a/lib/build_OID_registry b/lib/build_OID_registry new file mode 100755 index 000000000000..dfbdaab81bc8 --- /dev/null +++ b/lib/build_OID_registry | |||
@@ -0,0 +1,209 @@ | |||
1 | #!/usr/bin/perl -w | ||
2 | # | ||
3 | # Build a static ASN.1 Object Identified (OID) registry | ||
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 | |||
14 | use strict; | ||
15 | |||
16 | my @names = (); | ||
17 | my @oids = (); | ||
18 | |||
19 | if ($#ARGV != 1) { | ||
20 | print STDERR "Format: ", $0, " <in-h-file> <out-c-file>\n"; | ||
21 | exit(2); | ||
22 | } | ||
23 | |||
24 | # | ||
25 | # Open the file to read from | ||
26 | # | ||
27 | open IN_FILE, "<$ARGV[0]" || die; | ||
28 | while (<IN_FILE>) { | ||
29 | chomp; | ||
30 | if (m!\s+OID_([a-zA-z][a-zA-Z0-9_]+),\s+/[*]\s+([012][.0-9]*)\s+[*]/!) { | ||
31 | push @names, $1; | ||
32 | push @oids, $2; | ||
33 | } | ||
34 | } | ||
35 | close IN_FILE || die; | ||
36 | |||
37 | # | ||
38 | # Open the files to write into | ||
39 | # | ||
40 | open C_FILE, ">$ARGV[1]" or die; | ||
41 | print C_FILE "/*\n"; | ||
42 | print C_FILE " * Automatically generated by ", $0, ". Do not edit\n"; | ||
43 | print C_FILE " */\n"; | ||
44 | |||
45 | # | ||
46 | # Split the data up into separate lists and also determine the lengths of the | ||
47 | # encoded data arrays. | ||
48 | # | ||
49 | my @indices = (); | ||
50 | my @lengths = (); | ||
51 | my $total_length = 0; | ||
52 | |||
53 | print "Compiling ", $#names + 1, " OIDs\n"; | ||
54 | |||
55 | for (my $i = 0; $i <= $#names; $i++) { | ||
56 | my $name = $names[$i]; | ||
57 | my $oid = $oids[$i]; | ||
58 | |||
59 | my @components = split(/[.]/, $oid); | ||
60 | |||
61 | # Determine the encoded length of this OID | ||
62 | my $size = $#components; | ||
63 | for (my $loop = 2; $loop <= $#components; $loop++) { | ||
64 | my $c = $components[$loop]; | ||
65 | |||
66 | # We will base128 encode the number | ||
67 | my $tmp = ($c == 0) ? 0 : int(log($c)/log(2)); | ||
68 | $tmp = int($tmp / 7); | ||
69 | $size += $tmp; | ||
70 | } | ||
71 | push @lengths, $size; | ||
72 | push @indices, $total_length; | ||
73 | $total_length += $size; | ||
74 | } | ||
75 | |||
76 | # | ||
77 | # Emit the look-up-by-OID index table | ||
78 | # | ||
79 | print C_FILE "\n"; | ||
80 | if ($total_length <= 255) { | ||
81 | print C_FILE "static const unsigned char oid_index[OID__NR + 1] = {\n"; | ||
82 | } else { | ||
83 | print C_FILE "static const unsigned short oid_index[OID__NR + 1] = {\n"; | ||
84 | } | ||
85 | for (my $i = 0; $i <= $#names; $i++) { | ||
86 | print C_FILE "\t[OID_", $names[$i], "] = ", $indices[$i], ",\n" | ||
87 | } | ||
88 | print C_FILE "\t[OID__NR] = ", $total_length, "\n"; | ||
89 | print C_FILE "};\n"; | ||
90 | |||
91 | # | ||
92 | # Encode the OIDs | ||
93 | # | ||
94 | my @encoded_oids = (); | ||
95 | |||
96 | for (my $i = 0; $i <= $#names; $i++) { | ||
97 | my @octets = (); | ||
98 | |||
99 | my @components = split(/[.]/, $oids[$i]); | ||
100 | |||
101 | push @octets, $components[0] * 40 + $components[1]; | ||
102 | |||
103 | for (my $loop = 2; $loop <= $#components; $loop++) { | ||
104 | my $c = $components[$loop]; | ||
105 | |||
106 | # Base128 encode the number | ||
107 | my $tmp = ($c == 0) ? 0 : int(log($c)/log(2)); | ||
108 | $tmp = int($tmp / 7); | ||
109 | |||
110 | for (; $tmp > 0; $tmp--) { | ||
111 | push @octets, (($c >> $tmp * 7) & 0x7f) | 0x80; | ||
112 | } | ||
113 | push @octets, $c & 0x7f; | ||
114 | } | ||
115 | |||
116 | push @encoded_oids, \@octets; | ||
117 | } | ||
118 | |||
119 | # | ||
120 | # Create a hash value for each OID | ||
121 | # | ||
122 | my @hash_values = (); | ||
123 | for (my $i = 0; $i <= $#names; $i++) { | ||
124 | my @octets = @{$encoded_oids[$i]}; | ||
125 | |||
126 | my $hash = $#octets; | ||
127 | foreach (@octets) { | ||
128 | $hash += $_ * 33; | ||
129 | } | ||
130 | |||
131 | $hash = ($hash >> 24) ^ ($hash >> 16) ^ ($hash >> 8) ^ ($hash); | ||
132 | |||
133 | push @hash_values, $hash & 0xff; | ||
134 | } | ||
135 | |||
136 | # | ||
137 | # Emit the OID data | ||
138 | # | ||
139 | print C_FILE "\n"; | ||
140 | print C_FILE "static const unsigned char oid_data[", $total_length, "] = {\n"; | ||
141 | for (my $i = 0; $i <= $#names; $i++) { | ||
142 | my @octets = @{$encoded_oids[$i]}; | ||
143 | print C_FILE "\t"; | ||
144 | print C_FILE $_, ", " foreach (@octets); | ||
145 | print C_FILE "\t// ", $names[$i]; | ||
146 | print C_FILE "\n"; | ||
147 | } | ||
148 | print C_FILE "};\n"; | ||
149 | |||
150 | # | ||
151 | # Build the search index table (ordered by length then hash then content) | ||
152 | # | ||
153 | my @index_table = ( 0 .. $#names ); | ||
154 | |||
155 | @index_table = sort { | ||
156 | my @octets_a = @{$encoded_oids[$a]}; | ||
157 | my @octets_b = @{$encoded_oids[$b]}; | ||
158 | |||
159 | return $hash_values[$a] <=> $hash_values[$b] | ||
160 | if ($hash_values[$a] != $hash_values[$b]); | ||
161 | return $#octets_a <=> $#octets_b | ||
162 | if ($#octets_a != $#octets_b); | ||
163 | for (my $i = $#octets_a; $i >= 0; $i--) { | ||
164 | return $octets_a[$i] <=> $octets_b[$i] | ||
165 | if ($octets_a[$i] != $octets_b[$i]); | ||
166 | } | ||
167 | return 0; | ||
168 | |||
169 | } @index_table; | ||
170 | |||
171 | # | ||
172 | # Emit the search index and hash value table | ||
173 | # | ||
174 | print C_FILE "\n"; | ||
175 | print C_FILE "static const struct {\n"; | ||
176 | print C_FILE "\tunsigned char hash;\n"; | ||
177 | if ($#names <= 255) { | ||
178 | print C_FILE "\tenum OID oid : 8;\n"; | ||
179 | } else { | ||
180 | print C_FILE "\tenum OID oid : 16;\n"; | ||
181 | } | ||
182 | print C_FILE "} oid_search_table[OID__NR] = {\n"; | ||
183 | for (my $i = 0; $i <= $#names; $i++) { | ||
184 | my @octets = @{$encoded_oids[$index_table[$i]]}; | ||
185 | printf(C_FILE "\t[%3u] = { %3u, OID_%-35s }, // ", | ||
186 | $i, | ||
187 | $hash_values[$index_table[$i]], | ||
188 | $names[$index_table[$i]]); | ||
189 | printf C_FILE "%02x", $_ foreach (@octets); | ||
190 | print C_FILE "\n"; | ||
191 | } | ||
192 | print C_FILE "};\n"; | ||
193 | |||
194 | # | ||
195 | # Emit the OID debugging name table | ||
196 | # | ||
197 | #print C_FILE "\n"; | ||
198 | #print C_FILE "const char *const oid_name_table[OID__NR + 1] = {\n"; | ||
199 | # | ||
200 | #for (my $i = 0; $i <= $#names; $i++) { | ||
201 | # print C_FILE "\t\"", $names[$i], "\",\n" | ||
202 | #} | ||
203 | #print C_FILE "\t\"Unknown-OID\"\n"; | ||
204 | #print C_FILE "};\n"; | ||
205 | |||
206 | # | ||
207 | # Polish off | ||
208 | # | ||
209 | close C_FILE or die; | ||
diff --git a/lib/mpi/Makefile b/lib/mpi/Makefile index 45ca90a8639c..019a68c90144 100644 --- a/lib/mpi/Makefile +++ b/lib/mpi/Makefile | |||
@@ -14,6 +14,7 @@ mpi-y = \ | |||
14 | generic_mpih-add1.o \ | 14 | generic_mpih-add1.o \ |
15 | mpicoder.o \ | 15 | mpicoder.o \ |
16 | mpi-bit.o \ | 16 | mpi-bit.o \ |
17 | mpi-cmp.o \ | ||
17 | mpih-cmp.o \ | 18 | mpih-cmp.o \ |
18 | mpih-div.o \ | 19 | mpih-div.o \ |
19 | mpih-mul.o \ | 20 | mpih-mul.o \ |
diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h index 29f98624ef93..678ce4f1e124 100644 --- a/lib/mpi/longlong.h +++ b/lib/mpi/longlong.h | |||
@@ -19,6 +19,8 @@ | |||
19 | * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, | 19 | * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
20 | * MA 02111-1307, USA. */ | 20 | * MA 02111-1307, USA. */ |
21 | 21 | ||
22 | #include <asm-generic/bitops/count_zeros.h> | ||
23 | |||
22 | /* You have to define the following before including this file: | 24 | /* You have to define the following before including this file: |
23 | * | 25 | * |
24 | * UWtype -- An unsigned type, default type for operations (typically a "word") | 26 | * UWtype -- An unsigned type, default type for operations (typically a "word") |
@@ -146,12 +148,6 @@ do { \ | |||
146 | : "1" ((USItype)(n1)), \ | 148 | : "1" ((USItype)(n1)), \ |
147 | "r" ((USItype)(n0)), \ | 149 | "r" ((USItype)(n0)), \ |
148 | "r" ((USItype)(d))) | 150 | "r" ((USItype)(d))) |
149 | |||
150 | #define count_leading_zeros(count, x) \ | ||
151 | __asm__ ("clz %0,%1" \ | ||
152 | : "=r" ((USItype)(count)) \ | ||
153 | : "r" ((USItype)(x))) | ||
154 | #define COUNT_LEADING_ZEROS_0 32 | ||
155 | #endif /* __a29k__ */ | 151 | #endif /* __a29k__ */ |
156 | 152 | ||
157 | #if defined(__alpha) && W_TYPE_SIZE == 64 | 153 | #if defined(__alpha) && W_TYPE_SIZE == 64 |
@@ -298,11 +294,6 @@ extern UDItype __udiv_qrnnd(); | |||
298 | : "1" ((USItype)(nh)), \ | 294 | : "1" ((USItype)(nh)), \ |
299 | "0" ((USItype)(nl)), \ | 295 | "0" ((USItype)(nl)), \ |
300 | "g" ((USItype)(d))) | 296 | "g" ((USItype)(d))) |
301 | #define count_leading_zeros(count, x) \ | ||
302 | __asm__ ("bsch/1 %1,%0" \ | ||
303 | : "=g" (count) \ | ||
304 | : "g" ((USItype)(x)), \ | ||
305 | "0" ((USItype)0)) | ||
306 | #endif | 297 | #endif |
307 | 298 | ||
308 | /*************************************** | 299 | /*************************************** |
@@ -354,27 +345,6 @@ do { USItype __r; \ | |||
354 | } while (0) | 345 | } while (0) |
355 | extern USItype __udiv_qrnnd(); | 346 | extern USItype __udiv_qrnnd(); |
356 | #endif /* LONGLONG_STANDALONE */ | 347 | #endif /* LONGLONG_STANDALONE */ |
357 | #define count_leading_zeros(count, x) \ | ||
358 | do { \ | ||
359 | USItype __tmp; \ | ||
360 | __asm__ ( \ | ||
361 | "ldi 1,%0\n" \ | ||
362 | "extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \ | ||
363 | "extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n" \ | ||
364 | "ldo 16(%0),%0 ; Yes. Perform add.\n" \ | ||
365 | "extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \ | ||
366 | "extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n" \ | ||
367 | "ldo 8(%0),%0 ; Yes. Perform add.\n" \ | ||
368 | "extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \ | ||
369 | "extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n" \ | ||
370 | "ldo 4(%0),%0 ; Yes. Perform add.\n" \ | ||
371 | "extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \ | ||
372 | "extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n" \ | ||
373 | "ldo 2(%0),%0 ; Yes. Perform add.\n" \ | ||
374 | "extru %1,30,1,%1 ; Extract bit 1.\n" \ | ||
375 | "sub %0,%1,%0 ; Subtract it. " \ | ||
376 | : "=r" (count), "=r" (__tmp) : "1" (x)); \ | ||
377 | } while (0) | ||
378 | #endif /* hppa */ | 348 | #endif /* hppa */ |
379 | 349 | ||
380 | /*************************************** | 350 | /*************************************** |
@@ -457,15 +427,6 @@ do { \ | |||
457 | : "0" ((USItype)(n0)), \ | 427 | : "0" ((USItype)(n0)), \ |
458 | "1" ((USItype)(n1)), \ | 428 | "1" ((USItype)(n1)), \ |
459 | "rm" ((USItype)(d))) | 429 | "rm" ((USItype)(d))) |
460 | #define count_leading_zeros(count, x) \ | ||
461 | do { \ | ||
462 | USItype __cbtmp; \ | ||
463 | __asm__ ("bsrl %1,%0" \ | ||
464 | : "=r" (__cbtmp) : "rm" ((USItype)(x))); \ | ||
465 | (count) = __cbtmp ^ 31; \ | ||
466 | } while (0) | ||
467 | #define count_trailing_zeros(count, x) \ | ||
468 | __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x))) | ||
469 | #ifndef UMUL_TIME | 430 | #ifndef UMUL_TIME |
470 | #define UMUL_TIME 40 | 431 | #define UMUL_TIME 40 |
471 | #endif | 432 | #endif |
@@ -536,15 +497,6 @@ do { \ | |||
536 | "dI" ((USItype)(d))); \ | 497 | "dI" ((USItype)(d))); \ |
537 | (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ | 498 | (r) = __rq.__i.__l; (q) = __rq.__i.__h; \ |
538 | } while (0) | 499 | } while (0) |
539 | #define count_leading_zeros(count, x) \ | ||
540 | do { \ | ||
541 | USItype __cbtmp; \ | ||
542 | __asm__ ("scanbit %1,%0" \ | ||
543 | : "=r" (__cbtmp) \ | ||
544 | : "r" ((USItype)(x))); \ | ||
545 | (count) = __cbtmp ^ 31; \ | ||
546 | } while (0) | ||
547 | #define COUNT_LEADING_ZEROS_0 (-32) /* sic */ | ||
548 | #if defined(__i960mx) /* what is the proper symbol to test??? */ | 500 | #if defined(__i960mx) /* what is the proper symbol to test??? */ |
549 | #define rshift_rhlc(r, h, l, c) \ | 501 | #define rshift_rhlc(r, h, l, c) \ |
550 | do { \ | 502 | do { \ |
@@ -603,11 +555,6 @@ do { \ | |||
603 | : "0" ((USItype)(n0)), \ | 555 | : "0" ((USItype)(n0)), \ |
604 | "1" ((USItype)(n1)), \ | 556 | "1" ((USItype)(n1)), \ |
605 | "dmi" ((USItype)(d))) | 557 | "dmi" ((USItype)(d))) |
606 | #define count_leading_zeros(count, x) \ | ||
607 | __asm__ ("bfffo %1{%b2:%b2},%0" \ | ||
608 | : "=d" ((USItype)(count)) \ | ||
609 | : "od" ((USItype)(x)), "n" (0)) | ||
610 | #define COUNT_LEADING_ZEROS_0 32 | ||
611 | #else /* not mc68020 */ | 558 | #else /* not mc68020 */ |
612 | #define umul_ppmm(xh, xl, a, b) \ | 559 | #define umul_ppmm(xh, xl, a, b) \ |
613 | do { USItype __umul_tmp1, __umul_tmp2; \ | 560 | do { USItype __umul_tmp1, __umul_tmp2; \ |
@@ -664,15 +611,6 @@ do { USItype __umul_tmp1, __umul_tmp2; \ | |||
664 | "rJ" ((USItype)(bh)), \ | 611 | "rJ" ((USItype)(bh)), \ |
665 | "rJ" ((USItype)(al)), \ | 612 | "rJ" ((USItype)(al)), \ |
666 | "rJ" ((USItype)(bl))) | 613 | "rJ" ((USItype)(bl))) |
667 | #define count_leading_zeros(count, x) \ | ||
668 | do { \ | ||
669 | USItype __cbtmp; \ | ||
670 | __asm__ ("ff1 %0,%1" \ | ||
671 | : "=r" (__cbtmp) \ | ||
672 | : "r" ((USItype)(x))); \ | ||
673 | (count) = __cbtmp ^ 31; \ | ||
674 | } while (0) | ||
675 | #define COUNT_LEADING_ZEROS_0 63 /* sic */ | ||
676 | #if defined(__m88110__) | 614 | #if defined(__m88110__) |
677 | #define umul_ppmm(wh, wl, u, v) \ | 615 | #define umul_ppmm(wh, wl, u, v) \ |
678 | do { \ | 616 | do { \ |
@@ -779,12 +717,6 @@ do { \ | |||
779 | : "0" (__xx.__ll), \ | 717 | : "0" (__xx.__ll), \ |
780 | "g" ((USItype)(d))); \ | 718 | "g" ((USItype)(d))); \ |
781 | (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) | 719 | (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) |
782 | #define count_trailing_zeros(count, x) \ | ||
783 | do { \ | ||
784 | __asm__("ffsd %2,%0" \ | ||
785 | : "=r"((USItype) (count)) \ | ||
786 | : "0"((USItype) 0), "r"((USItype) (x))); \ | ||
787 | } while (0) | ||
788 | #endif /* __ns32000__ */ | 720 | #endif /* __ns32000__ */ |
789 | 721 | ||
790 | /*************************************** | 722 | /*************************************** |
@@ -855,11 +787,6 @@ do { \ | |||
855 | "rI" ((USItype)(al)), \ | 787 | "rI" ((USItype)(al)), \ |
856 | "r" ((USItype)(bl))); \ | 788 | "r" ((USItype)(bl))); \ |
857 | } while (0) | 789 | } while (0) |
858 | #define count_leading_zeros(count, x) \ | ||
859 | __asm__ ("{cntlz|cntlzw} %0,%1" \ | ||
860 | : "=r" ((USItype)(count)) \ | ||
861 | : "r" ((USItype)(x))) | ||
862 | #define COUNT_LEADING_ZEROS_0 32 | ||
863 | #if defined(_ARCH_PPC) | 790 | #if defined(_ARCH_PPC) |
864 | #define umul_ppmm(ph, pl, m0, m1) \ | 791 | #define umul_ppmm(ph, pl, m0, m1) \ |
865 | do { \ | 792 | do { \ |
@@ -1001,19 +928,6 @@ do { \ | |||
1001 | } while (0) | 928 | } while (0) |
1002 | #define UMUL_TIME 20 | 929 | #define UMUL_TIME 20 |
1003 | #define UDIV_TIME 200 | 930 | #define UDIV_TIME 200 |
1004 | #define count_leading_zeros(count, x) \ | ||
1005 | do { \ | ||
1006 | if ((x) >= 0x10000) \ | ||
1007 | __asm__ ("clz %0,%1" \ | ||
1008 | : "=r" ((USItype)(count)) \ | ||
1009 | : "r" ((USItype)(x) >> 16)); \ | ||
1010 | else { \ | ||
1011 | __asm__ ("clz %0,%1" \ | ||
1012 | : "=r" ((USItype)(count)) \ | ||
1013 | : "r" ((USItype)(x))); \ | ||
1014 | (count) += 16; \ | ||
1015 | } \ | ||
1016 | } while (0) | ||
1017 | #endif /* RT/ROMP */ | 931 | #endif /* RT/ROMP */ |
1018 | 932 | ||
1019 | /*************************************** | 933 | /*************************************** |
@@ -1142,13 +1056,6 @@ do { \ | |||
1142 | "rI" ((USItype)(d)) \ | 1056 | "rI" ((USItype)(d)) \ |
1143 | : "%g1" __AND_CLOBBER_CC) | 1057 | : "%g1" __AND_CLOBBER_CC) |
1144 | #define UDIV_TIME 37 | 1058 | #define UDIV_TIME 37 |
1145 | #define count_leading_zeros(count, x) \ | ||
1146 | __asm__ ("scan %1,0,%0" \ | ||
1147 | : "=r" ((USItype)(x)) \ | ||
1148 | : "r" ((USItype)(count))) | ||
1149 | /* Early sparclites return 63 for an argument of 0, but they warn that future | ||
1150 | implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 | ||
1151 | undefined. */ | ||
1152 | #endif /* __sparclite__ */ | 1059 | #endif /* __sparclite__ */ |
1153 | #endif /* __sparc_v8__ */ | 1060 | #endif /* __sparc_v8__ */ |
1154 | /* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ | 1061 | /* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd. */ |
@@ -1454,47 +1361,6 @@ do { \ | |||
1454 | #define udiv_qrnnd __udiv_qrnnd_c | 1361 | #define udiv_qrnnd __udiv_qrnnd_c |
1455 | #endif | 1362 | #endif |
1456 | 1363 | ||
1457 | #undef count_leading_zeros | ||
1458 | #if !defined(count_leading_zeros) | ||
1459 | extern | ||
1460 | #ifdef __STDC__ | ||
1461 | const | ||
1462 | #endif | ||
1463 | unsigned char __clz_tab[]; | ||
1464 | #define count_leading_zeros(count, x) \ | ||
1465 | do { \ | ||
1466 | UWtype __xr = (x); \ | ||
1467 | UWtype __a; \ | ||
1468 | \ | ||
1469 | if (W_TYPE_SIZE <= 32) { \ | ||
1470 | __a = __xr < ((UWtype) 1 << 2*__BITS4) \ | ||
1471 | ? (__xr < ((UWtype) 1 << __BITS4) ? 0 : __BITS4) \ | ||
1472 | : (__xr < ((UWtype) 1 << 3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ | ||
1473 | } \ | ||
1474 | else { \ | ||
1475 | for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ | ||
1476 | if (((__xr >> __a) & 0xff) != 0) \ | ||
1477 | break; \ | ||
1478 | } \ | ||
1479 | \ | ||
1480 | (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ | ||
1481 | } while (0) | ||
1482 | /* This version gives a well-defined value for zero. */ | ||
1483 | #define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE | ||
1484 | #endif | ||
1485 | |||
1486 | #if !defined(count_trailing_zeros) | ||
1487 | /* Define count_trailing_zeros using count_leading_zeros. The latter might be | ||
1488 | defined in asm, but if it is not, the C version above is good enough. */ | ||
1489 | #define count_trailing_zeros(count, x) \ | ||
1490 | do { \ | ||
1491 | UWtype __ctz_x = (x); \ | ||
1492 | UWtype __ctz_c; \ | ||
1493 | count_leading_zeros(__ctz_c, __ctz_x & -__ctz_x); \ | ||
1494 | (count) = W_TYPE_SIZE - 1 - __ctz_c; \ | ||
1495 | } while (0) | ||
1496 | #endif | ||
1497 | |||
1498 | #ifndef UDIV_NEEDS_NORMALIZATION | 1364 | #ifndef UDIV_NEEDS_NORMALIZATION |
1499 | #define UDIV_NEEDS_NORMALIZATION 0 | 1365 | #define UDIV_NEEDS_NORMALIZATION 0 |
1500 | #endif | 1366 | #endif |
diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c index 568724804f29..503537e08436 100644 --- a/lib/mpi/mpi-bit.c +++ b/lib/mpi/mpi-bit.c | |||
@@ -45,7 +45,7 @@ unsigned mpi_get_nbits(MPI a) | |||
45 | if (a->nlimbs) { | 45 | if (a->nlimbs) { |
46 | mpi_limb_t alimb = a->d[a->nlimbs - 1]; | 46 | mpi_limb_t alimb = a->d[a->nlimbs - 1]; |
47 | if (alimb) | 47 | if (alimb) |
48 | count_leading_zeros(n, alimb); | 48 | n = count_leading_zeros(alimb); |
49 | else | 49 | else |
50 | n = BITS_PER_MPI_LIMB; | 50 | n = BITS_PER_MPI_LIMB; |
51 | n = BITS_PER_MPI_LIMB - n + (a->nlimbs - 1) * BITS_PER_MPI_LIMB; | 51 | n = BITS_PER_MPI_LIMB - n + (a->nlimbs - 1) * BITS_PER_MPI_LIMB; |
diff --git a/lib/mpi/mpi-cmp.c b/lib/mpi/mpi-cmp.c new file mode 100644 index 000000000000..1871e7b61ca0 --- /dev/null +++ b/lib/mpi/mpi-cmp.c | |||
@@ -0,0 +1,70 @@ | |||
1 | /* mpi-cmp.c - MPI functions | ||
2 | * Copyright (C) 1998, 1999 Free Software Foundation, Inc. | ||
3 | * | ||
4 | * This file is part of GnuPG. | ||
5 | * | ||
6 | * GnuPG is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * GnuPG is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
19 | */ | ||
20 | |||
21 | #include "mpi-internal.h" | ||
22 | |||
23 | int mpi_cmp_ui(MPI u, unsigned long v) | ||
24 | { | ||
25 | mpi_limb_t limb = v; | ||
26 | |||
27 | mpi_normalize(u); | ||
28 | if (!u->nlimbs && !limb) | ||
29 | return 0; | ||
30 | if (u->sign) | ||
31 | return -1; | ||
32 | if (u->nlimbs > 1) | ||
33 | return 1; | ||
34 | |||
35 | if (u->d[0] == limb) | ||
36 | return 0; | ||
37 | else if (u->d[0] > limb) | ||
38 | return 1; | ||
39 | else | ||
40 | return -1; | ||
41 | } | ||
42 | EXPORT_SYMBOL_GPL(mpi_cmp_ui); | ||
43 | |||
44 | int mpi_cmp(MPI u, MPI v) | ||
45 | { | ||
46 | mpi_size_t usize, vsize; | ||
47 | int cmp; | ||
48 | |||
49 | mpi_normalize(u); | ||
50 | mpi_normalize(v); | ||
51 | usize = u->nlimbs; | ||
52 | vsize = v->nlimbs; | ||
53 | if (!u->sign && v->sign) | ||
54 | return 1; | ||
55 | if (u->sign && !v->sign) | ||
56 | return -1; | ||
57 | if (usize != vsize && !u->sign && !v->sign) | ||
58 | return usize - vsize; | ||
59 | if (usize != vsize && u->sign && v->sign) | ||
60 | return vsize + usize; | ||
61 | if (!usize) | ||
62 | return 0; | ||
63 | cmp = mpihelp_cmp(u->d, v->d, usize); | ||
64 | if (!cmp) | ||
65 | return 0; | ||
66 | if ((cmp < 0 ? 1 : 0) == (u->sign ? 1 : 0)) | ||
67 | return 1; | ||
68 | return -1; | ||
69 | } | ||
70 | EXPORT_SYMBOL_GPL(mpi_cmp); | ||
diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c index 67f3e79af914..5464c8744ea9 100644 --- a/lib/mpi/mpi-pow.c +++ b/lib/mpi/mpi-pow.c | |||
@@ -77,7 +77,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) | |||
77 | mp = mp_marker = mpi_alloc_limb_space(msize); | 77 | mp = mp_marker = mpi_alloc_limb_space(msize); |
78 | if (!mp) | 78 | if (!mp) |
79 | goto enomem; | 79 | goto enomem; |
80 | count_leading_zeros(mod_shift_cnt, mod->d[msize - 1]); | 80 | mod_shift_cnt = count_leading_zeros(mod->d[msize - 1]); |
81 | if (mod_shift_cnt) | 81 | if (mod_shift_cnt) |
82 | mpihelp_lshift(mp, mod->d, msize, mod_shift_cnt); | 82 | mpihelp_lshift(mp, mod->d, msize, mod_shift_cnt); |
83 | else | 83 | else |
@@ -169,7 +169,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) | |||
169 | 169 | ||
170 | i = esize - 1; | 170 | i = esize - 1; |
171 | e = ep[i]; | 171 | e = ep[i]; |
172 | count_leading_zeros(c, e); | 172 | c = count_leading_zeros(e); |
173 | e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ | 173 | e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ |
174 | c = BITS_PER_MPI_LIMB - 1 - c; | 174 | c = BITS_PER_MPI_LIMB - 1 - c; |
175 | 175 | ||
diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index f0fa65995800..3962b7f7fe3f 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c | |||
@@ -18,10 +18,65 @@ | |||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | 18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/bitops.h> | ||
22 | #include <asm-generic/bitops/count_zeros.h> | ||
21 | #include "mpi-internal.h" | 23 | #include "mpi-internal.h" |
22 | 24 | ||
23 | #define MAX_EXTERN_MPI_BITS 16384 | 25 | #define MAX_EXTERN_MPI_BITS 16384 |
24 | 26 | ||
27 | /** | ||
28 | * mpi_read_raw_data - Read a raw byte stream as a positive integer | ||
29 | * @xbuffer: The data to read | ||
30 | * @nbytes: The amount of data to read | ||
31 | */ | ||
32 | MPI mpi_read_raw_data(const void *xbuffer, size_t nbytes) | ||
33 | { | ||
34 | const uint8_t *buffer = xbuffer; | ||
35 | int i, j; | ||
36 | unsigned nbits, nlimbs; | ||
37 | mpi_limb_t a; | ||
38 | MPI val = NULL; | ||
39 | |||
40 | while (nbytes >= 0 && buffer[0] == 0) { | ||
41 | buffer++; | ||
42 | nbytes--; | ||
43 | } | ||
44 | |||
45 | nbits = nbytes * 8; | ||
46 | if (nbits > MAX_EXTERN_MPI_BITS) { | ||
47 | pr_info("MPI: mpi too large (%u bits)\n", nbits); | ||
48 | return NULL; | ||
49 | } | ||
50 | if (nbytes > 0) | ||
51 | nbits -= count_leading_zeros(buffer[0]); | ||
52 | else | ||
53 | nbits = 0; | ||
54 | |||
55 | nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB; | ||
56 | val = mpi_alloc(nlimbs); | ||
57 | if (!val) | ||
58 | return NULL; | ||
59 | val->nbits = nbits; | ||
60 | val->sign = 0; | ||
61 | val->nlimbs = nlimbs; | ||
62 | |||
63 | if (nbytes > 0) { | ||
64 | i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB; | ||
65 | i %= BYTES_PER_MPI_LIMB; | ||
66 | for (j = nlimbs; j > 0; j--) { | ||
67 | a = 0; | ||
68 | for (; i < BYTES_PER_MPI_LIMB; i++) { | ||
69 | a <<= 8; | ||
70 | a |= *buffer++; | ||
71 | } | ||
72 | i = 0; | ||
73 | val->d[j - 1] = a; | ||
74 | } | ||
75 | } | ||
76 | return val; | ||
77 | } | ||
78 | EXPORT_SYMBOL_GPL(mpi_read_raw_data); | ||
79 | |||
25 | MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) | 80 | MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread) |
26 | { | 81 | { |
27 | const uint8_t *buffer = xbuffer; | 82 | const uint8_t *buffer = xbuffer; |
diff --git a/lib/oid_registry.c b/lib/oid_registry.c new file mode 100644 index 000000000000..d8de11f45908 --- /dev/null +++ b/lib/oid_registry.c | |||
@@ -0,0 +1,170 @@ | |||
1 | /* ASN.1 Object identifier (OID) registry | ||
2 | * | ||
3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/export.h> | ||
13 | #include <linux/oid_registry.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/bug.h> | ||
17 | #include "oid_registry_data.c" | ||
18 | |||
19 | /** | ||
20 | * look_up_OID - Find an OID registration for the specified data | ||
21 | * @data: Binary representation of the OID | ||
22 | * @datasize: Size of the binary representation | ||
23 | */ | ||
24 | enum OID look_up_OID(const void *data, size_t datasize) | ||
25 | { | ||
26 | const unsigned char *octets = data; | ||
27 | enum OID oid; | ||
28 | unsigned char xhash; | ||
29 | unsigned i, j, k, hash; | ||
30 | size_t len; | ||
31 | |||
32 | /* Hash the OID data */ | ||
33 | hash = datasize - 1; | ||
34 | |||
35 | for (i = 0; i < datasize; i++) | ||
36 | hash += octets[i] * 33; | ||
37 | hash = (hash >> 24) ^ (hash >> 16) ^ (hash >> 8) ^ hash; | ||
38 | hash &= 0xff; | ||
39 | |||
40 | /* Binary search the OID registry. OIDs are stored in ascending order | ||
41 | * of hash value then ascending order of size and then in ascending | ||
42 | * order of reverse value. | ||
43 | */ | ||
44 | i = 0; | ||
45 | k = OID__NR; | ||
46 | while (i < k) { | ||
47 | j = (i + k) / 2; | ||
48 | |||
49 | xhash = oid_search_table[j].hash; | ||
50 | if (xhash > hash) { | ||
51 | k = j; | ||
52 | continue; | ||
53 | } | ||
54 | if (xhash < hash) { | ||
55 | i = j + 1; | ||
56 | continue; | ||
57 | } | ||
58 | |||
59 | oid = oid_search_table[j].oid; | ||
60 | len = oid_index[oid + 1] - oid_index[oid]; | ||
61 | if (len > datasize) { | ||
62 | k = j; | ||
63 | continue; | ||
64 | } | ||
65 | if (len < datasize) { | ||
66 | i = j + 1; | ||
67 | continue; | ||
68 | } | ||
69 | |||
70 | /* Variation is most likely to be at the tail end of the | ||
71 | * OID, so do the comparison in reverse. | ||
72 | */ | ||
73 | while (len > 0) { | ||
74 | unsigned char a = oid_data[oid_index[oid] + --len]; | ||
75 | unsigned char b = octets[len]; | ||
76 | if (a > b) { | ||
77 | k = j; | ||
78 | goto next; | ||
79 | } | ||
80 | if (a < b) { | ||
81 | i = j + 1; | ||
82 | goto next; | ||
83 | } | ||
84 | } | ||
85 | return oid; | ||
86 | next: | ||
87 | ; | ||
88 | } | ||
89 | |||
90 | return OID__NR; | ||
91 | } | ||
92 | EXPORT_SYMBOL_GPL(look_up_OID); | ||
93 | |||
94 | /* | ||
95 | * sprint_OID - Print an Object Identifier into a buffer | ||
96 | * @data: The encoded OID to print | ||
97 | * @datasize: The size of the encoded OID | ||
98 | * @buffer: The buffer to render into | ||
99 | * @bufsize: The size of the buffer | ||
100 | * | ||
101 | * The OID is rendered into the buffer in "a.b.c.d" format and the number of | ||
102 | * bytes is returned. -EBADMSG is returned if the data could not be intepreted | ||
103 | * and -ENOBUFS if the buffer was too small. | ||
104 | */ | ||
105 | int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize) | ||
106 | { | ||
107 | const unsigned char *v = data, *end = v + datasize; | ||
108 | unsigned long num; | ||
109 | unsigned char n; | ||
110 | size_t ret; | ||
111 | int count; | ||
112 | |||
113 | if (v >= end) | ||
114 | return -EBADMSG; | ||
115 | |||
116 | n = *v++; | ||
117 | ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40); | ||
118 | buffer += count; | ||
119 | bufsize -= count; | ||
120 | if (bufsize == 0) | ||
121 | return -ENOBUFS; | ||
122 | |||
123 | while (v < end) { | ||
124 | num = 0; | ||
125 | n = *v++; | ||
126 | if (!(n & 0x80)) { | ||
127 | num = n; | ||
128 | } else { | ||
129 | num = n & 0x7f; | ||
130 | do { | ||
131 | if (v >= end) | ||
132 | return -EBADMSG; | ||
133 | n = *v++; | ||
134 | num <<= 7; | ||
135 | num |= n & 0x7f; | ||
136 | } while (n & 0x80); | ||
137 | } | ||
138 | ret += count = snprintf(buffer, bufsize, ".%lu", num); | ||
139 | buffer += count; | ||
140 | bufsize -= count; | ||
141 | if (bufsize == 0) | ||
142 | return -ENOBUFS; | ||
143 | } | ||
144 | |||
145 | return ret; | ||
146 | } | ||
147 | EXPORT_SYMBOL_GPL(sprint_oid); | ||
148 | |||
149 | /** | ||
150 | * sprint_OID - Print an Object Identifier into a buffer | ||
151 | * @oid: The OID to print | ||
152 | * @buffer: The buffer to render into | ||
153 | * @bufsize: The size of the buffer | ||
154 | * | ||
155 | * The OID is rendered into the buffer in "a.b.c.d" format and the number of | ||
156 | * bytes is returned. | ||
157 | */ | ||
158 | int sprint_OID(enum OID oid, char *buffer, size_t bufsize) | ||
159 | { | ||
160 | int ret; | ||
161 | |||
162 | BUG_ON(oid >= OID__NR); | ||
163 | |||
164 | ret = sprint_oid(oid_data + oid_index[oid], | ||
165 | oid_index[oid + 1] - oid_index[oid], | ||
166 | buffer, bufsize); | ||
167 | BUG_ON(ret == -EBADMSG); | ||
168 | return ret; | ||
169 | } | ||
170 | EXPORT_SYMBOL_GPL(sprint_OID); | ||
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index 9da7fdd3cd8a..af14cb425164 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c | |||
@@ -423,14 +423,15 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, | |||
423 | } | 423 | } |
424 | } | 424 | } |
425 | 425 | ||
426 | int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) | 426 | int ceph_key_instantiate(struct key *key, struct key_preparsed_payload *prep) |
427 | { | 427 | { |
428 | struct ceph_crypto_key *ckey; | 428 | struct ceph_crypto_key *ckey; |
429 | size_t datalen = prep->datalen; | ||
429 | int ret; | 430 | int ret; |
430 | void *p; | 431 | void *p; |
431 | 432 | ||
432 | ret = -EINVAL; | 433 | ret = -EINVAL; |
433 | if (datalen <= 0 || datalen > 32767 || !data) | 434 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
434 | goto err; | 435 | goto err; |
435 | 436 | ||
436 | ret = key_payload_reserve(key, datalen); | 437 | ret = key_payload_reserve(key, datalen); |
@@ -443,8 +444,8 @@ int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) | |||
443 | goto err; | 444 | goto err; |
444 | 445 | ||
445 | /* TODO ceph_crypto_key_decode should really take const input */ | 446 | /* TODO ceph_crypto_key_decode should really take const input */ |
446 | p = (void *)data; | 447 | p = (void *)prep->data; |
447 | ret = ceph_crypto_key_decode(ckey, &p, (char*)data+datalen); | 448 | ret = ceph_crypto_key_decode(ckey, &p, (char*)prep->data+datalen); |
448 | if (ret < 0) | 449 | if (ret < 0) |
449 | goto err_ckey; | 450 | goto err_ckey; |
450 | 451 | ||
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index 9807945a56d9..8aa4b1115384 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c | |||
@@ -59,13 +59,13 @@ const struct cred *dns_resolver_cache; | |||
59 | * "ip1,ip2,...#foo=bar" | 59 | * "ip1,ip2,...#foo=bar" |
60 | */ | 60 | */ |
61 | static int | 61 | static int |
62 | dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen) | 62 | dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep) |
63 | { | 63 | { |
64 | struct user_key_payload *upayload; | 64 | struct user_key_payload *upayload; |
65 | unsigned long derrno; | 65 | unsigned long derrno; |
66 | int ret; | 66 | int ret; |
67 | size_t result_len = 0; | 67 | size_t datalen = prep->datalen, result_len = 0; |
68 | const char *data = _data, *end, *opt; | 68 | const char *data = prep->data, *end, *opt; |
69 | 69 | ||
70 | kenter("%%%d,%s,'%*.*s',%zu", | 70 | kenter("%%%d,%s,'%*.*s',%zu", |
71 | key->serial, key->description, | 71 | key->serial, key->description, |
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index 011d2384b115..7633a752c65e 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c | |||
@@ -26,8 +26,8 @@ | |||
26 | #include "ar-internal.h" | 26 | #include "ar-internal.h" |
27 | 27 | ||
28 | static int rxrpc_vet_description_s(const char *); | 28 | static int rxrpc_vet_description_s(const char *); |
29 | static int rxrpc_instantiate(struct key *, const void *, size_t); | 29 | static int rxrpc_instantiate(struct key *, struct key_preparsed_payload *); |
30 | static int rxrpc_instantiate_s(struct key *, const void *, size_t); | 30 | static int rxrpc_instantiate_s(struct key *, struct key_preparsed_payload *); |
31 | static void rxrpc_destroy(struct key *); | 31 | static void rxrpc_destroy(struct key *); |
32 | static void rxrpc_destroy_s(struct key *); | 32 | static void rxrpc_destroy_s(struct key *); |
33 | static void rxrpc_describe(const struct key *, struct seq_file *); | 33 | static void rxrpc_describe(const struct key *, struct seq_file *); |
@@ -678,7 +678,7 @@ error: | |||
678 | * | 678 | * |
679 | * if no data is provided, then a no-security key is made | 679 | * if no data is provided, then a no-security key is made |
680 | */ | 680 | */ |
681 | static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) | 681 | static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep) |
682 | { | 682 | { |
683 | const struct rxrpc_key_data_v1 *v1; | 683 | const struct rxrpc_key_data_v1 *v1; |
684 | struct rxrpc_key_token *token, **pp; | 684 | struct rxrpc_key_token *token, **pp; |
@@ -686,26 +686,26 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) | |||
686 | u32 kver; | 686 | u32 kver; |
687 | int ret; | 687 | int ret; |
688 | 688 | ||
689 | _enter("{%x},,%zu", key_serial(key), datalen); | 689 | _enter("{%x},,%zu", key_serial(key), prep->datalen); |
690 | 690 | ||
691 | /* handle a no-security key */ | 691 | /* handle a no-security key */ |
692 | if (!data && datalen == 0) | 692 | if (!prep->data && prep->datalen == 0) |
693 | return 0; | 693 | return 0; |
694 | 694 | ||
695 | /* determine if the XDR payload format is being used */ | 695 | /* determine if the XDR payload format is being used */ |
696 | if (datalen > 7 * 4) { | 696 | if (prep->datalen > 7 * 4) { |
697 | ret = rxrpc_instantiate_xdr(key, data, datalen); | 697 | ret = rxrpc_instantiate_xdr(key, prep->data, prep->datalen); |
698 | if (ret != -EPROTO) | 698 | if (ret != -EPROTO) |
699 | return ret; | 699 | return ret; |
700 | } | 700 | } |
701 | 701 | ||
702 | /* get the key interface version number */ | 702 | /* get the key interface version number */ |
703 | ret = -EINVAL; | 703 | ret = -EINVAL; |
704 | if (datalen <= 4 || !data) | 704 | if (prep->datalen <= 4 || !prep->data) |
705 | goto error; | 705 | goto error; |
706 | memcpy(&kver, data, sizeof(kver)); | 706 | memcpy(&kver, prep->data, sizeof(kver)); |
707 | data += sizeof(kver); | 707 | prep->data += sizeof(kver); |
708 | datalen -= sizeof(kver); | 708 | prep->datalen -= sizeof(kver); |
709 | 709 | ||
710 | _debug("KEY I/F VERSION: %u", kver); | 710 | _debug("KEY I/F VERSION: %u", kver); |
711 | 711 | ||
@@ -715,11 +715,11 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) | |||
715 | 715 | ||
716 | /* deal with a version 1 key */ | 716 | /* deal with a version 1 key */ |
717 | ret = -EINVAL; | 717 | ret = -EINVAL; |
718 | if (datalen < sizeof(*v1)) | 718 | if (prep->datalen < sizeof(*v1)) |
719 | goto error; | 719 | goto error; |
720 | 720 | ||
721 | v1 = data; | 721 | v1 = prep->data; |
722 | if (datalen != sizeof(*v1) + v1->ticket_length) | 722 | if (prep->datalen != sizeof(*v1) + v1->ticket_length) |
723 | goto error; | 723 | goto error; |
724 | 724 | ||
725 | _debug("SCIX: %u", v1->security_index); | 725 | _debug("SCIX: %u", v1->security_index); |
@@ -784,17 +784,17 @@ error: | |||
784 | * instantiate a server secret key | 784 | * instantiate a server secret key |
785 | * data should be a pointer to the 8-byte secret key | 785 | * data should be a pointer to the 8-byte secret key |
786 | */ | 786 | */ |
787 | static int rxrpc_instantiate_s(struct key *key, const void *data, | 787 | static int rxrpc_instantiate_s(struct key *key, |
788 | size_t datalen) | 788 | struct key_preparsed_payload *prep) |
789 | { | 789 | { |
790 | struct crypto_blkcipher *ci; | 790 | struct crypto_blkcipher *ci; |
791 | 791 | ||
792 | _enter("{%x},,%zu", key_serial(key), datalen); | 792 | _enter("{%x},,%zu", key_serial(key), prep->datalen); |
793 | 793 | ||
794 | if (datalen != 8) | 794 | if (prep->datalen != 8) |
795 | return -EINVAL; | 795 | return -EINVAL; |
796 | 796 | ||
797 | memcpy(&key->type_data, data, 8); | 797 | memcpy(&key->type_data, prep->data, 8); |
798 | 798 | ||
799 | ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); | 799 | ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); |
800 | if (IS_ERR(ci)) { | 800 | if (IS_ERR(ci)) { |
@@ -802,7 +802,7 @@ static int rxrpc_instantiate_s(struct key *key, const void *data, | |||
802 | return PTR_ERR(ci); | 802 | return PTR_ERR(ci); |
803 | } | 803 | } |
804 | 804 | ||
805 | if (crypto_blkcipher_setkey(ci, data, 8) < 0) | 805 | if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0) |
806 | BUG(); | 806 | BUG(); |
807 | 807 | ||
808 | key->payload.data = ci; | 808 | key->payload.data = ci; |
diff --git a/scripts/.gitignore b/scripts/.gitignore index 65f362d931b5..fb070fa1038f 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore | |||
@@ -10,3 +10,4 @@ ihex2fw | |||
10 | recordmcount | 10 | recordmcount |
11 | docproc | 11 | docproc |
12 | sortextable | 12 | sortextable |
13 | asn1_compiler | ||
diff --git a/scripts/Makefile b/scripts/Makefile index a55b0067758a..01e7adb838d9 100644 --- a/scripts/Makefile +++ b/scripts/Makefile | |||
@@ -16,8 +16,10 @@ hostprogs-$(CONFIG_VT) += conmakehash | |||
16 | hostprogs-$(CONFIG_IKCONFIG) += bin2c | 16 | hostprogs-$(CONFIG_IKCONFIG) += bin2c |
17 | hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount | 17 | hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount |
18 | hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable | 18 | hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable |
19 | hostprogs-$(CONFIG_ASN1) += asn1_compiler | ||
19 | 20 | ||
20 | HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include | 21 | HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include |
22 | HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include | ||
21 | 23 | ||
22 | always := $(hostprogs-y) $(hostprogs-m) | 24 | always := $(hostprogs-y) $(hostprogs-m) |
23 | 25 | ||
diff --git a/scripts/Makefile.build b/scripts/Makefile.build index ff1720d28d0c..0e801c3cdaf8 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build | |||
@@ -354,6 +354,17 @@ quiet_cmd_cpp_lds_S = LDS $@ | |||
354 | $(obj)/%.lds: $(src)/%.lds.S FORCE | 354 | $(obj)/%.lds: $(src)/%.lds.S FORCE |
355 | $(call if_changed_dep,cpp_lds_S) | 355 | $(call if_changed_dep,cpp_lds_S) |
356 | 356 | ||
357 | # ASN.1 grammar | ||
358 | # --------------------------------------------------------------------------- | ||
359 | quiet_cmd_asn1_compiler = ASN.1 $@ | ||
360 | cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \ | ||
361 | $(subst .h,.c,$@) $(subst .c,.h,$@) | ||
362 | |||
363 | .PRECIOUS: $(objtree)/$(obj)/%-asn1.c $(objtree)/$(obj)/%-asn1.h | ||
364 | |||
365 | $(obj)/%-asn1.c $(obj)/%-asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler | ||
366 | $(call cmd,asn1_compiler) | ||
367 | |||
357 | # Build the compiled-in targets | 368 | # Build the compiled-in targets |
358 | # --------------------------------------------------------------------------- | 369 | # --------------------------------------------------------------------------- |
359 | 370 | ||
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index a1cb0222ebe6..002089141df4 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost | |||
@@ -14,7 +14,8 @@ | |||
14 | # 3) create one <module>.mod.c file pr. module | 14 | # 3) create one <module>.mod.c file pr. module |
15 | # 4) create one Module.symvers file with CRC for all exported symbols | 15 | # 4) create one Module.symvers file with CRC for all exported symbols |
16 | # 5) compile all <module>.mod.c files | 16 | # 5) compile all <module>.mod.c files |
17 | # 6) final link of the module to a <module.ko> file | 17 | # 6) final link of the module to a <module.ko> (or <module.unsigned>) file |
18 | # 7) signs the modules to a <module.ko> file | ||
18 | 19 | ||
19 | # Step 3 is used to place certain information in the module's ELF | 20 | # Step 3 is used to place certain information in the module's ELF |
20 | # section, including information such as: | 21 | # section, including information such as: |
@@ -32,6 +33,8 @@ | |||
32 | # Step 4 is solely used to allow module versioning in external modules, | 33 | # Step 4 is solely used to allow module versioning in external modules, |
33 | # where the CRC of each module is retrieved from the Module.symvers file. | 34 | # where the CRC of each module is retrieved from the Module.symvers file. |
34 | 35 | ||
36 | # Step 7 is dependent on CONFIG_MODULE_SIG being enabled. | ||
37 | |||
35 | # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined | 38 | # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined |
36 | # symbols in the final module linking stage | 39 | # symbols in the final module linking stage |
37 | # KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules. | 40 | # KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules. |
@@ -116,6 +119,7 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE | |||
116 | targets += $(modules:.ko=.mod.o) | 119 | targets += $(modules:.ko=.mod.o) |
117 | 120 | ||
118 | # Step 6), final link of the modules | 121 | # Step 6), final link of the modules |
122 | ifneq ($(CONFIG_MODULE_SIG),y) | ||
119 | quiet_cmd_ld_ko_o = LD [M] $@ | 123 | quiet_cmd_ld_ko_o = LD [M] $@ |
120 | cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ | 124 | cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ |
121 | $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ | 125 | $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ |
@@ -125,7 +129,78 @@ $(modules): %.ko :%.o %.mod.o FORCE | |||
125 | $(call if_changed,ld_ko_o) | 129 | $(call if_changed,ld_ko_o) |
126 | 130 | ||
127 | targets += $(modules) | 131 | targets += $(modules) |
132 | else | ||
133 | quiet_cmd_ld_ko_unsigned_o = LD [M] $@ | ||
134 | cmd_ld_ko_unsigned_o = \ | ||
135 | $(LD) -r $(LDFLAGS) \ | ||
136 | $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ | ||
137 | -o $@ $(filter-out FORCE,$^) \ | ||
138 | $(if $(AFTER_LINK),; $(AFTER_LINK)) | ||
139 | |||
140 | $(modules:.ko=.ko.unsigned): %.ko.unsigned :%.o %.mod.o FORCE | ||
141 | $(call if_changed,ld_ko_unsigned_o) | ||
142 | |||
143 | targets += $(modules:.ko=.ko.unsigned) | ||
144 | |||
145 | # Step 7), sign the modules | ||
146 | MODSECKEY = ./signing_key.priv | ||
147 | MODPUBKEY = ./signing_key.x509 | ||
148 | |||
149 | ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY)) | ||
150 | ifeq ($(KBUILD_SRC),) | ||
151 | # no O= is being used | ||
152 | SCRIPTS_DIR := scripts | ||
153 | else | ||
154 | SCRIPTS_DIR := $(KBUILD_SRC)/scripts | ||
155 | endif | ||
156 | SIGN_MODULES := 1 | ||
157 | else | ||
158 | SIGN_MODULES := 0 | ||
159 | endif | ||
160 | |||
161 | # only sign if it's an in-tree module | ||
162 | ifneq ($(KBUILD_EXTMOD),) | ||
163 | SIGN_MODULES := 0 | ||
164 | endif | ||
128 | 165 | ||
166 | # We strip the module as best we can - note that using both strip and eu-strip | ||
167 | # results in a smaller module than using either alone. | ||
168 | EU_STRIP = $(shell which eu-strip || echo true) | ||
169 | |||
170 | quiet_cmd_sign_ko_stripped_ko_unsigned = STRIP [M] $@ | ||
171 | cmd_sign_ko_stripped_ko_unsigned = \ | ||
172 | cp $< $@ && \ | ||
173 | strip -x -g $@ && \ | ||
174 | $(EU_STRIP) $@ | ||
175 | |||
176 | ifeq ($(SIGN_MODULES),1) | ||
177 | |||
178 | quiet_cmd_genkeyid = GENKEYID $@ | ||
179 | cmd_genkeyid = \ | ||
180 | perl $(SCRIPTS_DIR)/x509keyid $< $<.signer $<.keyid | ||
181 | |||
182 | %.signer %.keyid: % | ||
183 | $(call if_changed,genkeyid) | ||
184 | |||
185 | KEYRING_DEP := $(MODSECKEY) $(MODPUBKEY) $(MODPUBKEY).signer $(MODPUBKEY).keyid | ||
186 | quiet_cmd_sign_ko_ko_stripped = SIGN [M] $@ | ||
187 | cmd_sign_ko_ko_stripped = \ | ||
188 | sh $(SCRIPTS_DIR)/sign-file $(MODSECKEY) $(MODPUBKEY) $< $@ | ||
189 | else | ||
190 | KEYRING_DEP := | ||
191 | quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@ | ||
192 | cmd_sign_ko_ko_unsigned = \ | ||
193 | cp $< $@ | ||
194 | endif | ||
195 | |||
196 | $(modules): %.ko :%.ko.stripped $(KEYRING_DEP) FORCE | ||
197 | $(call if_changed,sign_ko_ko_stripped) | ||
198 | |||
199 | $(patsubst %.ko,%.ko.stripped,$(modules)): %.ko.stripped :%.ko.unsigned FORCE | ||
200 | $(call if_changed,sign_ko_stripped_ko_unsigned) | ||
201 | |||
202 | targets += $(modules) | ||
203 | endif | ||
129 | 204 | ||
130 | # Add FORCE to the prequisites of a target to force it to be always rebuilt. | 205 | # Add FORCE to the prequisites of a target to force it to be always rebuilt. |
131 | # --------------------------------------------------------------------------- | 206 | # --------------------------------------------------------------------------- |
diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c new file mode 100644 index 000000000000..db0e5cd34c70 --- /dev/null +++ b/scripts/asn1_compiler.c | |||
@@ -0,0 +1,1545 @@ | |||
1 | /* Simplified ASN.1 notation parser | ||
2 | * | ||
3 | * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <stdarg.h> | ||
13 | #include <stdio.h> | ||
14 | #include <stdlib.h> | ||
15 | #include <stdint.h> | ||
16 | #include <string.h> | ||
17 | #include <ctype.h> | ||
18 | #include <unistd.h> | ||
19 | #include <fcntl.h> | ||
20 | #include <sys/stat.h> | ||
21 | #include <linux/asn1_ber_bytecode.h> | ||
22 | |||
23 | enum token_type { | ||
24 | DIRECTIVE_ABSENT, | ||
25 | DIRECTIVE_ALL, | ||
26 | DIRECTIVE_ANY, | ||
27 | DIRECTIVE_APPLICATION, | ||
28 | DIRECTIVE_AUTOMATIC, | ||
29 | DIRECTIVE_BEGIN, | ||
30 | DIRECTIVE_BIT, | ||
31 | DIRECTIVE_BMPString, | ||
32 | DIRECTIVE_BOOLEAN, | ||
33 | DIRECTIVE_BY, | ||
34 | DIRECTIVE_CHARACTER, | ||
35 | DIRECTIVE_CHOICE, | ||
36 | DIRECTIVE_CLASS, | ||
37 | DIRECTIVE_COMPONENT, | ||
38 | DIRECTIVE_COMPONENTS, | ||
39 | DIRECTIVE_CONSTRAINED, | ||
40 | DIRECTIVE_CONTAINING, | ||
41 | DIRECTIVE_DEFAULT, | ||
42 | DIRECTIVE_DEFINED, | ||
43 | DIRECTIVE_DEFINITIONS, | ||
44 | DIRECTIVE_EMBEDDED, | ||
45 | DIRECTIVE_ENCODED, | ||
46 | DIRECTIVE_ENCODING_CONTROL, | ||
47 | DIRECTIVE_END, | ||
48 | DIRECTIVE_ENUMERATED, | ||
49 | DIRECTIVE_EXCEPT, | ||
50 | DIRECTIVE_EXPLICIT, | ||
51 | DIRECTIVE_EXPORTS, | ||
52 | DIRECTIVE_EXTENSIBILITY, | ||
53 | DIRECTIVE_EXTERNAL, | ||
54 | DIRECTIVE_FALSE, | ||
55 | DIRECTIVE_FROM, | ||
56 | DIRECTIVE_GeneralString, | ||
57 | DIRECTIVE_GeneralizedTime, | ||
58 | DIRECTIVE_GraphicString, | ||
59 | DIRECTIVE_IA5String, | ||
60 | DIRECTIVE_IDENTIFIER, | ||
61 | DIRECTIVE_IMPLICIT, | ||
62 | DIRECTIVE_IMPLIED, | ||
63 | DIRECTIVE_IMPORTS, | ||
64 | DIRECTIVE_INCLUDES, | ||
65 | DIRECTIVE_INSTANCE, | ||
66 | DIRECTIVE_INSTRUCTIONS, | ||
67 | DIRECTIVE_INTEGER, | ||
68 | DIRECTIVE_INTERSECTION, | ||
69 | DIRECTIVE_ISO646String, | ||
70 | DIRECTIVE_MAX, | ||
71 | DIRECTIVE_MIN, | ||
72 | DIRECTIVE_MINUS_INFINITY, | ||
73 | DIRECTIVE_NULL, | ||
74 | DIRECTIVE_NumericString, | ||
75 | DIRECTIVE_OBJECT, | ||
76 | DIRECTIVE_OCTET, | ||
77 | DIRECTIVE_OF, | ||
78 | DIRECTIVE_OPTIONAL, | ||
79 | DIRECTIVE_ObjectDescriptor, | ||
80 | DIRECTIVE_PATTERN, | ||
81 | DIRECTIVE_PDV, | ||
82 | DIRECTIVE_PLUS_INFINITY, | ||
83 | DIRECTIVE_PRESENT, | ||
84 | DIRECTIVE_PRIVATE, | ||
85 | DIRECTIVE_PrintableString, | ||
86 | DIRECTIVE_REAL, | ||
87 | DIRECTIVE_RELATIVE_OID, | ||
88 | DIRECTIVE_SEQUENCE, | ||
89 | DIRECTIVE_SET, | ||
90 | DIRECTIVE_SIZE, | ||
91 | DIRECTIVE_STRING, | ||
92 | DIRECTIVE_SYNTAX, | ||
93 | DIRECTIVE_T61String, | ||
94 | DIRECTIVE_TAGS, | ||
95 | DIRECTIVE_TRUE, | ||
96 | DIRECTIVE_TeletexString, | ||
97 | DIRECTIVE_UNION, | ||
98 | DIRECTIVE_UNIQUE, | ||
99 | DIRECTIVE_UNIVERSAL, | ||
100 | DIRECTIVE_UTCTime, | ||
101 | DIRECTIVE_UTF8String, | ||
102 | DIRECTIVE_UniversalString, | ||
103 | DIRECTIVE_VideotexString, | ||
104 | DIRECTIVE_VisibleString, | ||
105 | DIRECTIVE_WITH, | ||
106 | NR__DIRECTIVES, | ||
107 | TOKEN_ASSIGNMENT = NR__DIRECTIVES, | ||
108 | TOKEN_OPEN_CURLY, | ||
109 | TOKEN_CLOSE_CURLY, | ||
110 | TOKEN_OPEN_SQUARE, | ||
111 | TOKEN_CLOSE_SQUARE, | ||
112 | TOKEN_OPEN_ACTION, | ||
113 | TOKEN_CLOSE_ACTION, | ||
114 | TOKEN_COMMA, | ||
115 | TOKEN_NUMBER, | ||
116 | TOKEN_TYPE_NAME, | ||
117 | TOKEN_ELEMENT_NAME, | ||
118 | NR__TOKENS | ||
119 | }; | ||
120 | |||
121 | static const unsigned char token_to_tag[NR__TOKENS] = { | ||
122 | /* EOC goes first */ | ||
123 | [DIRECTIVE_BOOLEAN] = ASN1_BOOL, | ||
124 | [DIRECTIVE_INTEGER] = ASN1_INT, | ||
125 | [DIRECTIVE_BIT] = ASN1_BTS, | ||
126 | [DIRECTIVE_OCTET] = ASN1_OTS, | ||
127 | [DIRECTIVE_NULL] = ASN1_NULL, | ||
128 | [DIRECTIVE_OBJECT] = ASN1_OID, | ||
129 | [DIRECTIVE_ObjectDescriptor] = ASN1_ODE, | ||
130 | [DIRECTIVE_EXTERNAL] = ASN1_EXT, | ||
131 | [DIRECTIVE_REAL] = ASN1_REAL, | ||
132 | [DIRECTIVE_ENUMERATED] = ASN1_ENUM, | ||
133 | [DIRECTIVE_EMBEDDED] = 0, | ||
134 | [DIRECTIVE_UTF8String] = ASN1_UTF8STR, | ||
135 | [DIRECTIVE_RELATIVE_OID] = ASN1_RELOID, | ||
136 | /* 14 */ | ||
137 | /* 15 */ | ||
138 | [DIRECTIVE_SEQUENCE] = ASN1_SEQ, | ||
139 | [DIRECTIVE_SET] = ASN1_SET, | ||
140 | [DIRECTIVE_NumericString] = ASN1_NUMSTR, | ||
141 | [DIRECTIVE_PrintableString] = ASN1_PRNSTR, | ||
142 | [DIRECTIVE_T61String] = ASN1_TEXSTR, | ||
143 | [DIRECTIVE_TeletexString] = ASN1_TEXSTR, | ||
144 | [DIRECTIVE_VideotexString] = ASN1_VIDSTR, | ||
145 | [DIRECTIVE_IA5String] = ASN1_IA5STR, | ||
146 | [DIRECTIVE_UTCTime] = ASN1_UNITIM, | ||
147 | [DIRECTIVE_GeneralizedTime] = ASN1_GENTIM, | ||
148 | [DIRECTIVE_GraphicString] = ASN1_GRASTR, | ||
149 | [DIRECTIVE_VisibleString] = ASN1_VISSTR, | ||
150 | [DIRECTIVE_GeneralString] = ASN1_GENSTR, | ||
151 | [DIRECTIVE_UniversalString] = ASN1_UNITIM, | ||
152 | [DIRECTIVE_CHARACTER] = ASN1_CHRSTR, | ||
153 | [DIRECTIVE_BMPString] = ASN1_BMPSTR, | ||
154 | }; | ||
155 | |||
156 | static const char asn1_classes[4][5] = { | ||
157 | [ASN1_UNIV] = "UNIV", | ||
158 | [ASN1_APPL] = "APPL", | ||
159 | [ASN1_CONT] = "CONT", | ||
160 | [ASN1_PRIV] = "PRIV" | ||
161 | }; | ||
162 | |||
163 | static const char asn1_methods[2][5] = { | ||
164 | [ASN1_UNIV] = "PRIM", | ||
165 | [ASN1_APPL] = "CONS" | ||
166 | }; | ||
167 | |||
168 | static const char *const asn1_universal_tags[32] = { | ||
169 | "EOC", | ||
170 | "BOOL", | ||
171 | "INT", | ||
172 | "BTS", | ||
173 | "OTS", | ||
174 | "NULL", | ||
175 | "OID", | ||
176 | "ODE", | ||
177 | "EXT", | ||
178 | "REAL", | ||
179 | "ENUM", | ||
180 | "EPDV", | ||
181 | "UTF8STR", | ||
182 | "RELOID", | ||
183 | NULL, /* 14 */ | ||
184 | NULL, /* 15 */ | ||
185 | "SEQ", | ||
186 | "SET", | ||
187 | "NUMSTR", | ||
188 | "PRNSTR", | ||
189 | "TEXSTR", | ||
190 | "VIDSTR", | ||
191 | "IA5STR", | ||
192 | "UNITIM", | ||
193 | "GENTIM", | ||
194 | "GRASTR", | ||
195 | "VISSTR", | ||
196 | "GENSTR", | ||
197 | "UNISTR", | ||
198 | "CHRSTR", | ||
199 | "BMPSTR", | ||
200 | NULL /* 31 */ | ||
201 | }; | ||
202 | |||
203 | static const char *filename; | ||
204 | static const char *grammar_name; | ||
205 | static const char *outputname; | ||
206 | static const char *headername; | ||
207 | |||
208 | static const char *const directives[NR__DIRECTIVES] = { | ||
209 | #define _(X) [DIRECTIVE_##X] = #X | ||
210 | _(ABSENT), | ||
211 | _(ALL), | ||
212 | _(ANY), | ||
213 | _(APPLICATION), | ||
214 | _(AUTOMATIC), | ||
215 | _(BEGIN), | ||
216 | _(BIT), | ||
217 | _(BMPString), | ||
218 | _(BOOLEAN), | ||
219 | _(BY), | ||
220 | _(CHARACTER), | ||
221 | _(CHOICE), | ||
222 | _(CLASS), | ||
223 | _(COMPONENT), | ||
224 | _(COMPONENTS), | ||
225 | _(CONSTRAINED), | ||
226 | _(CONTAINING), | ||
227 | _(DEFAULT), | ||
228 | _(DEFINED), | ||
229 | _(DEFINITIONS), | ||
230 | _(EMBEDDED), | ||
231 | _(ENCODED), | ||
232 | [DIRECTIVE_ENCODING_CONTROL] = "ENCODING-CONTROL", | ||
233 | _(END), | ||
234 | _(ENUMERATED), | ||
235 | _(EXCEPT), | ||
236 | _(EXPLICIT), | ||
237 | _(EXPORTS), | ||
238 | _(EXTENSIBILITY), | ||
239 | _(EXTERNAL), | ||
240 | _(FALSE), | ||
241 | _(FROM), | ||
242 | _(GeneralString), | ||
243 | _(GeneralizedTime), | ||
244 | _(GraphicString), | ||
245 | _(IA5String), | ||
246 | _(IDENTIFIER), | ||
247 | _(IMPLICIT), | ||
248 | _(IMPLIED), | ||
249 | _(IMPORTS), | ||
250 | _(INCLUDES), | ||
251 | _(INSTANCE), | ||
252 | _(INSTRUCTIONS), | ||
253 | _(INTEGER), | ||
254 | _(INTERSECTION), | ||
255 | _(ISO646String), | ||
256 | _(MAX), | ||
257 | _(MIN), | ||
258 | [DIRECTIVE_MINUS_INFINITY] = "MINUS-INFINITY", | ||
259 | [DIRECTIVE_NULL] = "NULL", | ||
260 | _(NumericString), | ||
261 | _(OBJECT), | ||
262 | _(OCTET), | ||
263 | _(OF), | ||
264 | _(OPTIONAL), | ||
265 | _(ObjectDescriptor), | ||
266 | _(PATTERN), | ||
267 | _(PDV), | ||
268 | [DIRECTIVE_PLUS_INFINITY] = "PLUS-INFINITY", | ||
269 | _(PRESENT), | ||
270 | _(PRIVATE), | ||
271 | _(PrintableString), | ||
272 | _(REAL), | ||
273 | [DIRECTIVE_RELATIVE_OID] = "RELATIVE-OID", | ||
274 | _(SEQUENCE), | ||
275 | _(SET), | ||
276 | _(SIZE), | ||
277 | _(STRING), | ||
278 | _(SYNTAX), | ||
279 | _(T61String), | ||
280 | _(TAGS), | ||
281 | _(TRUE), | ||
282 | _(TeletexString), | ||
283 | _(UNION), | ||
284 | _(UNIQUE), | ||
285 | _(UNIVERSAL), | ||
286 | _(UTCTime), | ||
287 | _(UTF8String), | ||
288 | _(UniversalString), | ||
289 | _(VideotexString), | ||
290 | _(VisibleString), | ||
291 | _(WITH) | ||
292 | }; | ||
293 | |||
294 | struct action { | ||
295 | struct action *next; | ||
296 | unsigned char index; | ||
297 | char name[]; | ||
298 | }; | ||
299 | |||
300 | static struct action *action_list; | ||
301 | static unsigned nr_actions; | ||
302 | |||
303 | struct token { | ||
304 | unsigned short line; | ||
305 | enum token_type token_type : 8; | ||
306 | unsigned char size; | ||
307 | struct action *action; | ||
308 | const char *value; | ||
309 | struct type *type; | ||
310 | }; | ||
311 | |||
312 | static struct token *token_list; | ||
313 | static unsigned nr_tokens; | ||
314 | |||
315 | static int directive_compare(const void *_key, const void *_pdir) | ||
316 | { | ||
317 | const struct token *token = _key; | ||
318 | const char *const *pdir = _pdir, *dir = *pdir; | ||
319 | size_t dlen, clen; | ||
320 | int val; | ||
321 | |||
322 | dlen = strlen(dir); | ||
323 | clen = (dlen < token->size) ? dlen : token->size; | ||
324 | |||
325 | //printf("cmp(%*.*s,%s) = ", | ||
326 | // (int)token->size, (int)token->size, token->value, | ||
327 | // dir); | ||
328 | |||
329 | val = memcmp(token->value, dir, clen); | ||
330 | if (val != 0) { | ||
331 | //printf("%d [cmp]\n", val); | ||
332 | return val; | ||
333 | } | ||
334 | |||
335 | if (dlen == token->size) { | ||
336 | //printf("0\n"); | ||
337 | return 0; | ||
338 | } | ||
339 | //printf("%d\n", (int)dlen - (int)token->size); | ||
340 | return dlen - token->size; /* shorter -> negative */ | ||
341 | } | ||
342 | |||
343 | /* | ||
344 | * Tokenise an ASN.1 grammar | ||
345 | */ | ||
346 | static void tokenise(char *buffer, char *end) | ||
347 | { | ||
348 | struct token *tokens; | ||
349 | char *line, *nl, *p, *q; | ||
350 | unsigned tix, lineno; | ||
351 | |||
352 | /* Assume we're going to have half as many tokens as we have | ||
353 | * characters | ||
354 | */ | ||
355 | token_list = tokens = calloc((end - buffer) / 2, sizeof(struct token)); | ||
356 | if (!tokens) { | ||
357 | perror(NULL); | ||
358 | exit(1); | ||
359 | } | ||
360 | tix = 0; | ||
361 | |||
362 | lineno = 0; | ||
363 | while (buffer < end) { | ||
364 | /* First of all, break out a line */ | ||
365 | lineno++; | ||
366 | line = buffer; | ||
367 | nl = memchr(line, '\n', end - buffer); | ||
368 | if (!nl) { | ||
369 | buffer = nl = end; | ||
370 | } else { | ||
371 | buffer = nl + 1; | ||
372 | *nl = '\0'; | ||
373 | } | ||
374 | |||
375 | /* Remove "--" comments */ | ||
376 | p = line; | ||
377 | next_comment: | ||
378 | while ((p = memchr(p, '-', nl - p))) { | ||
379 | if (p[1] == '-') { | ||
380 | /* Found a comment; see if there's a terminator */ | ||
381 | q = p + 2; | ||
382 | while ((q = memchr(q, '-', nl - q))) { | ||
383 | if (q[1] == '-') { | ||
384 | /* There is - excise the comment */ | ||
385 | q += 2; | ||
386 | memmove(p, q, nl - q); | ||
387 | goto next_comment; | ||
388 | } | ||
389 | q++; | ||
390 | } | ||
391 | *p = '\0'; | ||
392 | nl = p; | ||
393 | break; | ||
394 | } else { | ||
395 | p++; | ||
396 | } | ||
397 | } | ||
398 | |||
399 | p = line; | ||
400 | while (p < nl) { | ||
401 | /* Skip white space */ | ||
402 | while (p < nl && isspace(*p)) | ||
403 | *(p++) = 0; | ||
404 | if (p >= nl) | ||
405 | break; | ||
406 | |||
407 | tokens[tix].line = lineno; | ||
408 | tokens[tix].value = p; | ||
409 | |||
410 | /* Handle string tokens */ | ||
411 | if (isalpha(*p)) { | ||
412 | const char **dir; | ||
413 | |||
414 | /* Can be a directive, type name or element | ||
415 | * name. Find the end of the name. | ||
416 | */ | ||
417 | q = p + 1; | ||
418 | while (q < nl && (isalnum(*q) || *q == '-' || *q == '_')) | ||
419 | q++; | ||
420 | tokens[tix].size = q - p; | ||
421 | p = q; | ||
422 | |||
423 | /* If it begins with a lowercase letter then | ||
424 | * it's an element name | ||
425 | */ | ||
426 | if (islower(tokens[tix].value[0])) { | ||
427 | tokens[tix++].token_type = TOKEN_ELEMENT_NAME; | ||
428 | continue; | ||
429 | } | ||
430 | |||
431 | /* Otherwise we need to search the directive | ||
432 | * table | ||
433 | */ | ||
434 | dir = bsearch(&tokens[tix], directives, | ||
435 | sizeof(directives) / sizeof(directives[1]), | ||
436 | sizeof(directives[1]), | ||
437 | directive_compare); | ||
438 | if (dir) { | ||
439 | tokens[tix++].token_type = dir - directives; | ||
440 | continue; | ||
441 | } | ||
442 | |||
443 | tokens[tix++].token_type = TOKEN_TYPE_NAME; | ||
444 | continue; | ||
445 | } | ||
446 | |||
447 | /* Handle numbers */ | ||
448 | if (isdigit(*p)) { | ||
449 | /* Find the end of the number */ | ||
450 | q = p + 1; | ||
451 | while (q < nl && (isdigit(*q))) | ||
452 | q++; | ||
453 | tokens[tix].size = q - p; | ||
454 | p = q; | ||
455 | tokens[tix++].token_type = TOKEN_NUMBER; | ||
456 | continue; | ||
457 | } | ||
458 | |||
459 | if (nl - p >= 3) { | ||
460 | if (memcmp(p, "::=", 3) == 0) { | ||
461 | p += 3; | ||
462 | tokens[tix].size = 3; | ||
463 | tokens[tix++].token_type = TOKEN_ASSIGNMENT; | ||
464 | continue; | ||
465 | } | ||
466 | } | ||
467 | |||
468 | if (nl - p >= 2) { | ||
469 | if (memcmp(p, "({", 2) == 0) { | ||
470 | p += 2; | ||
471 | tokens[tix].size = 2; | ||
472 | tokens[tix++].token_type = TOKEN_OPEN_ACTION; | ||
473 | continue; | ||
474 | } | ||
475 | if (memcmp(p, "})", 2) == 0) { | ||
476 | p += 2; | ||
477 | tokens[tix].size = 2; | ||
478 | tokens[tix++].token_type = TOKEN_CLOSE_ACTION; | ||
479 | continue; | ||
480 | } | ||
481 | } | ||
482 | |||
483 | if (nl - p >= 1) { | ||
484 | tokens[tix].size = 1; | ||
485 | switch (*p) { | ||
486 | case '{': | ||
487 | p += 1; | ||
488 | tokens[tix++].token_type = TOKEN_OPEN_CURLY; | ||
489 | continue; | ||
490 | case '}': | ||
491 | p += 1; | ||
492 | tokens[tix++].token_type = TOKEN_CLOSE_CURLY; | ||
493 | continue; | ||
494 | case '[': | ||
495 | p += 1; | ||
496 | tokens[tix++].token_type = TOKEN_OPEN_SQUARE; | ||
497 | continue; | ||
498 | case ']': | ||
499 | p += 1; | ||
500 | tokens[tix++].token_type = TOKEN_CLOSE_SQUARE; | ||
501 | continue; | ||
502 | case ',': | ||
503 | p += 1; | ||
504 | tokens[tix++].token_type = TOKEN_COMMA; | ||
505 | continue; | ||
506 | default: | ||
507 | break; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | fprintf(stderr, "%s:%u: Unknown character in grammar: '%c'\n", | ||
512 | filename, lineno, *p); | ||
513 | exit(1); | ||
514 | } | ||
515 | } | ||
516 | |||
517 | nr_tokens = tix; | ||
518 | printf("Extracted %u tokens\n", nr_tokens); | ||
519 | |||
520 | #if 0 | ||
521 | { | ||
522 | int n; | ||
523 | for (n = 0; n < nr_tokens; n++) | ||
524 | printf("Token %3u: '%*.*s'\n", | ||
525 | n, | ||
526 | (int)token_list[n].size, (int)token_list[n].size, | ||
527 | token_list[n].value); | ||
528 | } | ||
529 | #endif | ||
530 | } | ||
531 | |||
532 | static void build_type_list(void); | ||
533 | static void parse(void); | ||
534 | static void render(FILE *out, FILE *hdr); | ||
535 | |||
536 | /* | ||
537 | * | ||
538 | */ | ||
539 | int main(int argc, char **argv) | ||
540 | { | ||
541 | struct stat st; | ||
542 | ssize_t readlen; | ||
543 | FILE *out, *hdr; | ||
544 | char *buffer, *p; | ||
545 | int fd; | ||
546 | |||
547 | if (argc != 4) { | ||
548 | fprintf(stderr, "Format: %s <grammar-file> <c-file> <hdr-file>\n", | ||
549 | argv[0]); | ||
550 | exit(2); | ||
551 | } | ||
552 | |||
553 | filename = argv[1]; | ||
554 | outputname = argv[2]; | ||
555 | headername = argv[3]; | ||
556 | |||
557 | fd = open(filename, O_RDONLY); | ||
558 | if (fd < 0) { | ||
559 | perror(filename); | ||
560 | exit(1); | ||
561 | } | ||
562 | |||
563 | if (fstat(fd, &st) < 0) { | ||
564 | perror(filename); | ||
565 | exit(1); | ||
566 | } | ||
567 | |||
568 | if (!(buffer = malloc(st.st_size + 1))) { | ||
569 | perror(NULL); | ||
570 | exit(1); | ||
571 | } | ||
572 | |||
573 | if ((readlen = read(fd, buffer, st.st_size)) < 0) { | ||
574 | perror(filename); | ||
575 | exit(1); | ||
576 | } | ||
577 | |||
578 | if (close(fd) < 0) { | ||
579 | perror(filename); | ||
580 | exit(1); | ||
581 | } | ||
582 | |||
583 | if (readlen != st.st_size) { | ||
584 | fprintf(stderr, "%s: Short read\n", filename); | ||
585 | exit(1); | ||
586 | } | ||
587 | |||
588 | p = strrchr(argv[1], '/'); | ||
589 | p = p ? p + 1 : argv[1]; | ||
590 | grammar_name = strdup(p); | ||
591 | if (!p) { | ||
592 | perror(NULL); | ||
593 | exit(1); | ||
594 | } | ||
595 | p = strchr(grammar_name, '.'); | ||
596 | if (p) | ||
597 | *p = '\0'; | ||
598 | |||
599 | buffer[readlen] = 0; | ||
600 | tokenise(buffer, buffer + readlen); | ||
601 | build_type_list(); | ||
602 | parse(); | ||
603 | |||
604 | out = fopen(outputname, "w"); | ||
605 | if (!out) { | ||
606 | perror(outputname); | ||
607 | exit(1); | ||
608 | } | ||
609 | |||
610 | hdr = fopen(headername, "w"); | ||
611 | if (!out) { | ||
612 | perror(headername); | ||
613 | exit(1); | ||
614 | } | ||
615 | |||
616 | render(out, hdr); | ||
617 | |||
618 | if (fclose(out) < 0) { | ||
619 | perror(outputname); | ||
620 | exit(1); | ||
621 | } | ||
622 | |||
623 | if (fclose(hdr) < 0) { | ||
624 | perror(headername); | ||
625 | exit(1); | ||
626 | } | ||
627 | |||
628 | return 0; | ||
629 | } | ||
630 | |||
631 | enum compound { | ||
632 | NOT_COMPOUND, | ||
633 | SET, | ||
634 | SET_OF, | ||
635 | SEQUENCE, | ||
636 | SEQUENCE_OF, | ||
637 | CHOICE, | ||
638 | ANY, | ||
639 | TYPE_REF, | ||
640 | TAG_OVERRIDE | ||
641 | }; | ||
642 | |||
643 | struct element { | ||
644 | struct type *type_def; | ||
645 | struct token *name; | ||
646 | struct token *type; | ||
647 | struct action *action; | ||
648 | struct element *children; | ||
649 | struct element *next; | ||
650 | struct element *render_next; | ||
651 | struct element *list_next; | ||
652 | uint8_t n_elements; | ||
653 | enum compound compound : 8; | ||
654 | enum asn1_class class : 8; | ||
655 | enum asn1_method method : 8; | ||
656 | uint8_t tag; | ||
657 | unsigned entry_index; | ||
658 | unsigned flags; | ||
659 | #define ELEMENT_IMPLICIT 0x0001 | ||
660 | #define ELEMENT_EXPLICIT 0x0002 | ||
661 | #define ELEMENT_MARKED 0x0004 | ||
662 | #define ELEMENT_RENDERED 0x0008 | ||
663 | #define ELEMENT_SKIPPABLE 0x0010 | ||
664 | #define ELEMENT_CONDITIONAL 0x0020 | ||
665 | }; | ||
666 | |||
667 | struct type { | ||
668 | struct token *name; | ||
669 | struct token *def; | ||
670 | struct element *element; | ||
671 | unsigned ref_count; | ||
672 | unsigned flags; | ||
673 | #define TYPE_STOP_MARKER 0x0001 | ||
674 | #define TYPE_BEGIN 0x0002 | ||
675 | }; | ||
676 | |||
677 | static struct type *type_list; | ||
678 | static struct type **type_index; | ||
679 | static unsigned nr_types; | ||
680 | |||
681 | static int type_index_compare(const void *_a, const void *_b) | ||
682 | { | ||
683 | const struct type *const *a = _a, *const *b = _b; | ||
684 | |||
685 | if ((*a)->name->size != (*b)->name->size) | ||
686 | return (*a)->name->size - (*b)->name->size; | ||
687 | else | ||
688 | return memcmp((*a)->name->value, (*b)->name->value, | ||
689 | (*a)->name->size); | ||
690 | } | ||
691 | |||
692 | static int type_finder(const void *_key, const void *_ti) | ||
693 | { | ||
694 | const struct token *token = _key; | ||
695 | const struct type *const *ti = _ti; | ||
696 | const struct type *type = *ti; | ||
697 | |||
698 | if (token->size != type->name->size) | ||
699 | return token->size - type->name->size; | ||
700 | else | ||
701 | return memcmp(token->value, type->name->value, | ||
702 | token->size); | ||
703 | } | ||
704 | |||
705 | /* | ||
706 | * Build up a list of types and a sorted index to that list. | ||
707 | */ | ||
708 | static void build_type_list(void) | ||
709 | { | ||
710 | struct type *types; | ||
711 | unsigned nr, t, n; | ||
712 | |||
713 | nr = 0; | ||
714 | for (n = 0; n < nr_tokens - 1; n++) | ||
715 | if (token_list[n + 0].token_type == TOKEN_TYPE_NAME && | ||
716 | token_list[n + 1].token_type == TOKEN_ASSIGNMENT) | ||
717 | nr++; | ||
718 | |||
719 | if (nr == 0) { | ||
720 | fprintf(stderr, "%s: No defined types\n", filename); | ||
721 | exit(1); | ||
722 | } | ||
723 | |||
724 | nr_types = nr; | ||
725 | types = type_list = calloc(nr + 1, sizeof(type_list[0])); | ||
726 | if (!type_list) { | ||
727 | perror(NULL); | ||
728 | exit(1); | ||
729 | } | ||
730 | type_index = calloc(nr, sizeof(type_index[0])); | ||
731 | if (!type_index) { | ||
732 | perror(NULL); | ||
733 | exit(1); | ||
734 | } | ||
735 | |||
736 | t = 0; | ||
737 | types[t].flags |= TYPE_BEGIN; | ||
738 | for (n = 0; n < nr_tokens - 1; n++) { | ||
739 | if (token_list[n + 0].token_type == TOKEN_TYPE_NAME && | ||
740 | token_list[n + 1].token_type == TOKEN_ASSIGNMENT) { | ||
741 | types[t].name = &token_list[n]; | ||
742 | type_index[t] = &types[t]; | ||
743 | t++; | ||
744 | } | ||
745 | } | ||
746 | types[t].name = &token_list[n + 1]; | ||
747 | types[t].flags |= TYPE_STOP_MARKER; | ||
748 | |||
749 | qsort(type_index, nr, sizeof(type_index[0]), type_index_compare); | ||
750 | |||
751 | printf("Extracted %u types\n", nr_types); | ||
752 | #if 0 | ||
753 | for (n = 0; n < nr_types; n++) { | ||
754 | struct type *type = type_index[n]; | ||
755 | printf("- %*.*s\n", | ||
756 | (int)type->name->size, | ||
757 | (int)type->name->size, | ||
758 | type->name->value); | ||
759 | } | ||
760 | #endif | ||
761 | } | ||
762 | |||
763 | static struct element *parse_type(struct token **_cursor, struct token *stop, | ||
764 | struct token *name); | ||
765 | |||
766 | /* | ||
767 | * Parse the token stream | ||
768 | */ | ||
769 | static void parse(void) | ||
770 | { | ||
771 | struct token *cursor; | ||
772 | struct type *type; | ||
773 | |||
774 | /* Parse one type definition statement at a time */ | ||
775 | type = type_list; | ||
776 | do { | ||
777 | cursor = type->name; | ||
778 | |||
779 | if (cursor[0].token_type != TOKEN_TYPE_NAME || | ||
780 | cursor[1].token_type != TOKEN_ASSIGNMENT) | ||
781 | abort(); | ||
782 | cursor += 2; | ||
783 | |||
784 | type->element = parse_type(&cursor, type[1].name, NULL); | ||
785 | type->element->type_def = type; | ||
786 | |||
787 | if (cursor != type[1].name) { | ||
788 | fprintf(stderr, "%s:%d: Parse error at token '%*.*s'\n", | ||
789 | filename, cursor->line, | ||
790 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
791 | exit(1); | ||
792 | } | ||
793 | |||
794 | } while (type++, !(type->flags & TYPE_STOP_MARKER)); | ||
795 | |||
796 | printf("Extracted %u actions\n", nr_actions); | ||
797 | } | ||
798 | |||
799 | static struct element *element_list; | ||
800 | |||
801 | static struct element *alloc_elem(struct token *type) | ||
802 | { | ||
803 | struct element *e = calloc(1, sizeof(*e)); | ||
804 | if (!e) { | ||
805 | perror(NULL); | ||
806 | exit(1); | ||
807 | } | ||
808 | e->list_next = element_list; | ||
809 | element_list = e; | ||
810 | return e; | ||
811 | } | ||
812 | |||
813 | static struct element *parse_compound(struct token **_cursor, struct token *end, | ||
814 | int alternates); | ||
815 | |||
816 | /* | ||
817 | * Parse one type definition statement | ||
818 | */ | ||
819 | static struct element *parse_type(struct token **_cursor, struct token *end, | ||
820 | struct token *name) | ||
821 | { | ||
822 | struct element *top, *element; | ||
823 | struct action *action, **ppaction; | ||
824 | struct token *cursor = *_cursor; | ||
825 | struct type **ref; | ||
826 | char *p; | ||
827 | int labelled = 0, implicit = 0; | ||
828 | |||
829 | top = element = alloc_elem(cursor); | ||
830 | element->class = ASN1_UNIV; | ||
831 | element->method = ASN1_PRIM; | ||
832 | element->tag = token_to_tag[cursor->token_type]; | ||
833 | element->name = name; | ||
834 | |||
835 | /* Extract the tag value if one given */ | ||
836 | if (cursor->token_type == TOKEN_OPEN_SQUARE) { | ||
837 | cursor++; | ||
838 | if (cursor >= end) | ||
839 | goto overrun_error; | ||
840 | switch (cursor->token_type) { | ||
841 | case DIRECTIVE_UNIVERSAL: | ||
842 | element->class = ASN1_UNIV; | ||
843 | cursor++; | ||
844 | break; | ||
845 | case DIRECTIVE_APPLICATION: | ||
846 | element->class = ASN1_APPL; | ||
847 | cursor++; | ||
848 | break; | ||
849 | case TOKEN_NUMBER: | ||
850 | element->class = ASN1_CONT; | ||
851 | break; | ||
852 | case DIRECTIVE_PRIVATE: | ||
853 | element->class = ASN1_PRIV; | ||
854 | cursor++; | ||
855 | break; | ||
856 | default: | ||
857 | fprintf(stderr, "%s:%d: Unrecognised tag class token '%*.*s'\n", | ||
858 | filename, cursor->line, | ||
859 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
860 | exit(1); | ||
861 | } | ||
862 | |||
863 | if (cursor >= end) | ||
864 | goto overrun_error; | ||
865 | if (cursor->token_type != TOKEN_NUMBER) { | ||
866 | fprintf(stderr, "%s:%d: Missing tag number '%*.*s'\n", | ||
867 | filename, cursor->line, | ||
868 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
869 | exit(1); | ||
870 | } | ||
871 | |||
872 | element->tag &= ~0x1f; | ||
873 | element->tag |= strtoul(cursor->value, &p, 10); | ||
874 | if (p - cursor->value != cursor->size) | ||
875 | abort(); | ||
876 | cursor++; | ||
877 | |||
878 | if (cursor >= end) | ||
879 | goto overrun_error; | ||
880 | if (cursor->token_type != TOKEN_CLOSE_SQUARE) { | ||
881 | fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n", | ||
882 | filename, cursor->line, | ||
883 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
884 | exit(1); | ||
885 | } | ||
886 | cursor++; | ||
887 | if (cursor >= end) | ||
888 | goto overrun_error; | ||
889 | labelled = 1; | ||
890 | } | ||
891 | |||
892 | /* Handle implicit and explicit markers */ | ||
893 | if (cursor->token_type == DIRECTIVE_IMPLICIT) { | ||
894 | element->flags |= ELEMENT_IMPLICIT; | ||
895 | implicit = 1; | ||
896 | cursor++; | ||
897 | if (cursor >= end) | ||
898 | goto overrun_error; | ||
899 | } else if (cursor->token_type == DIRECTIVE_EXPLICIT) { | ||
900 | element->flags |= ELEMENT_EXPLICIT; | ||
901 | cursor++; | ||
902 | if (cursor >= end) | ||
903 | goto overrun_error; | ||
904 | } | ||
905 | |||
906 | if (labelled) { | ||
907 | if (!implicit) | ||
908 | element->method |= ASN1_CONS; | ||
909 | element->compound = implicit ? TAG_OVERRIDE : SEQUENCE; | ||
910 | element->children = alloc_elem(cursor); | ||
911 | element = element->children; | ||
912 | element->class = ASN1_UNIV; | ||
913 | element->method = ASN1_PRIM; | ||
914 | element->tag = token_to_tag[cursor->token_type]; | ||
915 | element->name = name; | ||
916 | } | ||
917 | |||
918 | /* Extract the type we're expecting here */ | ||
919 | element->type = cursor; | ||
920 | switch (cursor->token_type) { | ||
921 | case DIRECTIVE_ANY: | ||
922 | element->compound = ANY; | ||
923 | cursor++; | ||
924 | break; | ||
925 | |||
926 | case DIRECTIVE_NULL: | ||
927 | case DIRECTIVE_BOOLEAN: | ||
928 | case DIRECTIVE_ENUMERATED: | ||
929 | case DIRECTIVE_INTEGER: | ||
930 | element->compound = NOT_COMPOUND; | ||
931 | cursor++; | ||
932 | break; | ||
933 | |||
934 | case DIRECTIVE_EXTERNAL: | ||
935 | element->method = ASN1_CONS; | ||
936 | |||
937 | case DIRECTIVE_BMPString: | ||
938 | case DIRECTIVE_GeneralString: | ||
939 | case DIRECTIVE_GraphicString: | ||
940 | case DIRECTIVE_IA5String: | ||
941 | case DIRECTIVE_ISO646String: | ||
942 | case DIRECTIVE_NumericString: | ||
943 | case DIRECTIVE_PrintableString: | ||
944 | case DIRECTIVE_T61String: | ||
945 | case DIRECTIVE_TeletexString: | ||
946 | case DIRECTIVE_UniversalString: | ||
947 | case DIRECTIVE_UTF8String: | ||
948 | case DIRECTIVE_VideotexString: | ||
949 | case DIRECTIVE_VisibleString: | ||
950 | case DIRECTIVE_ObjectDescriptor: | ||
951 | case DIRECTIVE_GeneralizedTime: | ||
952 | case DIRECTIVE_UTCTime: | ||
953 | element->compound = NOT_COMPOUND; | ||
954 | cursor++; | ||
955 | break; | ||
956 | |||
957 | case DIRECTIVE_BIT: | ||
958 | case DIRECTIVE_OCTET: | ||
959 | element->compound = NOT_COMPOUND; | ||
960 | cursor++; | ||
961 | if (cursor >= end) | ||
962 | goto overrun_error; | ||
963 | if (cursor->token_type != DIRECTIVE_STRING) | ||
964 | goto parse_error; | ||
965 | cursor++; | ||
966 | break; | ||
967 | |||
968 | case DIRECTIVE_OBJECT: | ||
969 | element->compound = NOT_COMPOUND; | ||
970 | cursor++; | ||
971 | if (cursor >= end) | ||
972 | goto overrun_error; | ||
973 | if (cursor->token_type != DIRECTIVE_IDENTIFIER) | ||
974 | goto parse_error; | ||
975 | cursor++; | ||
976 | break; | ||
977 | |||
978 | case TOKEN_TYPE_NAME: | ||
979 | element->compound = TYPE_REF; | ||
980 | ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]), | ||
981 | type_finder); | ||
982 | if (!ref) { | ||
983 | fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n", | ||
984 | filename, cursor->line, | ||
985 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
986 | exit(1); | ||
987 | } | ||
988 | cursor->type = *ref; | ||
989 | (*ref)->ref_count++; | ||
990 | cursor++; | ||
991 | break; | ||
992 | |||
993 | case DIRECTIVE_CHOICE: | ||
994 | element->compound = CHOICE; | ||
995 | cursor++; | ||
996 | element->children = parse_compound(&cursor, end, 1); | ||
997 | break; | ||
998 | |||
999 | case DIRECTIVE_SEQUENCE: | ||
1000 | element->compound = SEQUENCE; | ||
1001 | element->method = ASN1_CONS; | ||
1002 | cursor++; | ||
1003 | if (cursor >= end) | ||
1004 | goto overrun_error; | ||
1005 | if (cursor->token_type == DIRECTIVE_OF) { | ||
1006 | element->compound = SEQUENCE_OF; | ||
1007 | cursor++; | ||
1008 | if (cursor >= end) | ||
1009 | goto overrun_error; | ||
1010 | element->children = parse_type(&cursor, end, NULL); | ||
1011 | } else { | ||
1012 | element->children = parse_compound(&cursor, end, 0); | ||
1013 | } | ||
1014 | break; | ||
1015 | |||
1016 | case DIRECTIVE_SET: | ||
1017 | element->compound = SET; | ||
1018 | element->method = ASN1_CONS; | ||
1019 | cursor++; | ||
1020 | if (cursor >= end) | ||
1021 | goto overrun_error; | ||
1022 | if (cursor->token_type == DIRECTIVE_OF) { | ||
1023 | element->compound = SET_OF; | ||
1024 | cursor++; | ||
1025 | if (cursor >= end) | ||
1026 | goto parse_error; | ||
1027 | element->children = parse_type(&cursor, end, NULL); | ||
1028 | } else { | ||
1029 | element->children = parse_compound(&cursor, end, 1); | ||
1030 | } | ||
1031 | break; | ||
1032 | |||
1033 | default: | ||
1034 | fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n", | ||
1035 | filename, cursor->line, | ||
1036 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
1037 | exit(1); | ||
1038 | } | ||
1039 | |||
1040 | /* Handle elements that are optional */ | ||
1041 | if (cursor < end && (cursor->token_type == DIRECTIVE_OPTIONAL || | ||
1042 | cursor->token_type == DIRECTIVE_DEFAULT) | ||
1043 | ) { | ||
1044 | cursor++; | ||
1045 | top->flags |= ELEMENT_SKIPPABLE; | ||
1046 | } | ||
1047 | |||
1048 | if (cursor < end && cursor->token_type == TOKEN_OPEN_ACTION) { | ||
1049 | cursor++; | ||
1050 | if (cursor >= end) | ||
1051 | goto overrun_error; | ||
1052 | if (cursor->token_type != TOKEN_ELEMENT_NAME) { | ||
1053 | fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n", | ||
1054 | filename, cursor->line, | ||
1055 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
1056 | exit(1); | ||
1057 | } | ||
1058 | |||
1059 | action = malloc(sizeof(struct action) + cursor->size + 1); | ||
1060 | if (!action) { | ||
1061 | perror(NULL); | ||
1062 | exit(1); | ||
1063 | } | ||
1064 | action->index = 0; | ||
1065 | memcpy(action->name, cursor->value, cursor->size); | ||
1066 | action->name[cursor->size] = 0; | ||
1067 | |||
1068 | for (ppaction = &action_list; | ||
1069 | *ppaction; | ||
1070 | ppaction = &(*ppaction)->next | ||
1071 | ) { | ||
1072 | int cmp = strcmp(action->name, (*ppaction)->name); | ||
1073 | if (cmp == 0) { | ||
1074 | free(action); | ||
1075 | action = *ppaction; | ||
1076 | goto found; | ||
1077 | } | ||
1078 | if (cmp < 0) { | ||
1079 | action->next = *ppaction; | ||
1080 | *ppaction = action; | ||
1081 | nr_actions++; | ||
1082 | goto found; | ||
1083 | } | ||
1084 | } | ||
1085 | action->next = NULL; | ||
1086 | *ppaction = action; | ||
1087 | nr_actions++; | ||
1088 | found: | ||
1089 | |||
1090 | element->action = action; | ||
1091 | cursor->action = action; | ||
1092 | cursor++; | ||
1093 | if (cursor >= end) | ||
1094 | goto overrun_error; | ||
1095 | if (cursor->token_type != TOKEN_CLOSE_ACTION) { | ||
1096 | fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n", | ||
1097 | filename, cursor->line, | ||
1098 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
1099 | exit(1); | ||
1100 | } | ||
1101 | cursor++; | ||
1102 | } | ||
1103 | |||
1104 | *_cursor = cursor; | ||
1105 | return top; | ||
1106 | |||
1107 | parse_error: | ||
1108 | fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n", | ||
1109 | filename, cursor->line, | ||
1110 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
1111 | exit(1); | ||
1112 | |||
1113 | overrun_error: | ||
1114 | fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename); | ||
1115 | exit(1); | ||
1116 | } | ||
1117 | |||
1118 | /* | ||
1119 | * Parse a compound type list | ||
1120 | */ | ||
1121 | static struct element *parse_compound(struct token **_cursor, struct token *end, | ||
1122 | int alternates) | ||
1123 | { | ||
1124 | struct element *children, **child_p = &children, *element; | ||
1125 | struct token *cursor = *_cursor, *name; | ||
1126 | |||
1127 | if (cursor->token_type != TOKEN_OPEN_CURLY) { | ||
1128 | fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n", | ||
1129 | filename, cursor->line, | ||
1130 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
1131 | exit(1); | ||
1132 | } | ||
1133 | cursor++; | ||
1134 | if (cursor >= end) | ||
1135 | goto overrun_error; | ||
1136 | |||
1137 | if (cursor->token_type == TOKEN_OPEN_CURLY) { | ||
1138 | fprintf(stderr, "%s:%d: Empty compound\n", | ||
1139 | filename, cursor->line); | ||
1140 | exit(1); | ||
1141 | } | ||
1142 | |||
1143 | for (;;) { | ||
1144 | name = NULL; | ||
1145 | if (cursor->token_type == TOKEN_ELEMENT_NAME) { | ||
1146 | name = cursor; | ||
1147 | cursor++; | ||
1148 | if (cursor >= end) | ||
1149 | goto overrun_error; | ||
1150 | } | ||
1151 | |||
1152 | element = parse_type(&cursor, end, name); | ||
1153 | if (alternates) | ||
1154 | element->flags |= ELEMENT_SKIPPABLE | ELEMENT_CONDITIONAL; | ||
1155 | |||
1156 | *child_p = element; | ||
1157 | child_p = &element->next; | ||
1158 | |||
1159 | if (cursor >= end) | ||
1160 | goto overrun_error; | ||
1161 | if (cursor->token_type != TOKEN_COMMA) | ||
1162 | break; | ||
1163 | cursor++; | ||
1164 | if (cursor >= end) | ||
1165 | goto overrun_error; | ||
1166 | } | ||
1167 | |||
1168 | children->flags &= ~ELEMENT_CONDITIONAL; | ||
1169 | |||
1170 | if (cursor->token_type != TOKEN_CLOSE_CURLY) { | ||
1171 | fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n", | ||
1172 | filename, cursor->line, | ||
1173 | (int)cursor->size, (int)cursor->size, cursor->value); | ||
1174 | exit(1); | ||
1175 | } | ||
1176 | cursor++; | ||
1177 | |||
1178 | *_cursor = cursor; | ||
1179 | return children; | ||
1180 | |||
1181 | overrun_error: | ||
1182 | fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename); | ||
1183 | exit(1); | ||
1184 | } | ||
1185 | |||
1186 | static void render_element(FILE *out, struct element *e, struct element *tag); | ||
1187 | static void render_out_of_line_list(FILE *out); | ||
1188 | |||
1189 | static int nr_entries; | ||
1190 | static int render_depth = 1; | ||
1191 | static struct element *render_list, **render_list_p = &render_list; | ||
1192 | |||
1193 | __attribute__((format(printf, 2, 3))) | ||
1194 | static void render_opcode(FILE *out, const char *fmt, ...) | ||
1195 | { | ||
1196 | va_list va; | ||
1197 | |||
1198 | if (out) { | ||
1199 | fprintf(out, "\t[%4d] =%*s", nr_entries, render_depth, ""); | ||
1200 | va_start(va, fmt); | ||
1201 | vfprintf(out, fmt, va); | ||
1202 | va_end(va); | ||
1203 | } | ||
1204 | nr_entries++; | ||
1205 | } | ||
1206 | |||
1207 | __attribute__((format(printf, 2, 3))) | ||
1208 | static void render_more(FILE *out, const char *fmt, ...) | ||
1209 | { | ||
1210 | va_list va; | ||
1211 | |||
1212 | if (out) { | ||
1213 | va_start(va, fmt); | ||
1214 | vfprintf(out, fmt, va); | ||
1215 | va_end(va); | ||
1216 | } | ||
1217 | } | ||
1218 | |||
1219 | /* | ||
1220 | * Render the grammar into a state machine definition. | ||
1221 | */ | ||
1222 | static void render(FILE *out, FILE *hdr) | ||
1223 | { | ||
1224 | struct element *e; | ||
1225 | struct action *action; | ||
1226 | struct type *root; | ||
1227 | int index; | ||
1228 | |||
1229 | fprintf(hdr, "/*\n"); | ||
1230 | fprintf(hdr, " * Automatically generated by asn1_compiler. Do not edit\n"); | ||
1231 | fprintf(hdr, " *\n"); | ||
1232 | fprintf(hdr, " * ASN.1 parser for %s\n", grammar_name); | ||
1233 | fprintf(hdr, " */\n"); | ||
1234 | fprintf(hdr, "#include <linux/asn1_decoder.h>\n"); | ||
1235 | fprintf(hdr, "\n"); | ||
1236 | fprintf(hdr, "extern const struct asn1_decoder %s_decoder;\n", grammar_name); | ||
1237 | if (ferror(hdr)) { | ||
1238 | perror(headername); | ||
1239 | exit(1); | ||
1240 | } | ||
1241 | |||
1242 | fprintf(out, "/*\n"); | ||
1243 | fprintf(out, " * Automatically generated by asn1_compiler. Do not edit\n"); | ||
1244 | fprintf(out, " *\n"); | ||
1245 | fprintf(out, " * ASN.1 parser for %s\n", grammar_name); | ||
1246 | fprintf(out, " */\n"); | ||
1247 | fprintf(out, "#include <linux/asn1_ber_bytecode.h>\n"); | ||
1248 | fprintf(out, "#include \"%s-asn1.h\"\n", grammar_name); | ||
1249 | fprintf(out, "\n"); | ||
1250 | if (ferror(out)) { | ||
1251 | perror(outputname); | ||
1252 | exit(1); | ||
1253 | } | ||
1254 | |||
1255 | /* Tabulate the action functions we might have to call */ | ||
1256 | fprintf(hdr, "\n"); | ||
1257 | index = 0; | ||
1258 | for (action = action_list; action; action = action->next) { | ||
1259 | action->index = index++; | ||
1260 | fprintf(hdr, | ||
1261 | "extern int %s(void *, size_t, unsigned char," | ||
1262 | " const void *, size_t);\n", | ||
1263 | action->name); | ||
1264 | } | ||
1265 | fprintf(hdr, "\n"); | ||
1266 | |||
1267 | fprintf(out, "enum %s_actions {\n", grammar_name); | ||
1268 | for (action = action_list; action; action = action->next) | ||
1269 | fprintf(out, "\tACT_%s = %u,\n", | ||
1270 | action->name, action->index); | ||
1271 | fprintf(out, "\tNR__%s_actions = %u\n", grammar_name, nr_actions); | ||
1272 | fprintf(out, "};\n"); | ||
1273 | |||
1274 | fprintf(out, "\n"); | ||
1275 | fprintf(out, "static const asn1_action_t %s_action_table[NR__%s_actions] = {\n", | ||
1276 | grammar_name, grammar_name); | ||
1277 | for (action = action_list; action; action = action->next) | ||
1278 | fprintf(out, "\t[%4u] = %s,\n", action->index, action->name); | ||
1279 | fprintf(out, "};\n"); | ||
1280 | |||
1281 | if (ferror(out)) { | ||
1282 | perror(outputname); | ||
1283 | exit(1); | ||
1284 | } | ||
1285 | |||
1286 | /* We do two passes - the first one calculates all the offsets */ | ||
1287 | printf("Pass 1\n"); | ||
1288 | nr_entries = 0; | ||
1289 | root = &type_list[0]; | ||
1290 | render_element(NULL, root->element, NULL); | ||
1291 | render_opcode(NULL, "ASN1_OP_COMPLETE,\n"); | ||
1292 | render_out_of_line_list(NULL); | ||
1293 | |||
1294 | for (e = element_list; e; e = e->list_next) | ||
1295 | e->flags &= ~ELEMENT_RENDERED; | ||
1296 | |||
1297 | /* And then we actually render */ | ||
1298 | printf("Pass 2\n"); | ||
1299 | fprintf(out, "\n"); | ||
1300 | fprintf(out, "static const unsigned char %s_machine[] = {\n", | ||
1301 | grammar_name); | ||
1302 | |||
1303 | nr_entries = 0; | ||
1304 | root = &type_list[0]; | ||
1305 | render_element(out, root->element, NULL); | ||
1306 | render_opcode(out, "ASN1_OP_COMPLETE,\n"); | ||
1307 | render_out_of_line_list(out); | ||
1308 | |||
1309 | fprintf(out, "};\n"); | ||
1310 | |||
1311 | fprintf(out, "\n"); | ||
1312 | fprintf(out, "const struct asn1_decoder %s_decoder = {\n", grammar_name); | ||
1313 | fprintf(out, "\t.machine = %s_machine,\n", grammar_name); | ||
1314 | fprintf(out, "\t.machlen = sizeof(%s_machine),\n", grammar_name); | ||
1315 | fprintf(out, "\t.actions = %s_action_table,\n", grammar_name); | ||
1316 | fprintf(out, "};\n"); | ||
1317 | } | ||
1318 | |||
1319 | /* | ||
1320 | * Render the out-of-line elements | ||
1321 | */ | ||
1322 | static void render_out_of_line_list(FILE *out) | ||
1323 | { | ||
1324 | struct element *e, *ce; | ||
1325 | const char *act; | ||
1326 | int entry; | ||
1327 | |||
1328 | while ((e = render_list)) { | ||
1329 | render_list = e->render_next; | ||
1330 | if (!render_list) | ||
1331 | render_list_p = &render_list; | ||
1332 | |||
1333 | render_more(out, "\n"); | ||
1334 | e->entry_index = entry = nr_entries; | ||
1335 | render_depth++; | ||
1336 | for (ce = e->children; ce; ce = ce->next) | ||
1337 | render_element(out, ce, NULL); | ||
1338 | render_depth--; | ||
1339 | |||
1340 | act = e->action ? "_ACT" : ""; | ||
1341 | switch (e->compound) { | ||
1342 | case SEQUENCE: | ||
1343 | render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act); | ||
1344 | break; | ||
1345 | case SEQUENCE_OF: | ||
1346 | render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act); | ||
1347 | render_opcode(out, "_jump_target(%u),\n", entry); | ||
1348 | break; | ||
1349 | case SET: | ||
1350 | render_opcode(out, "ASN1_OP_END_SET%s,\n", act); | ||
1351 | break; | ||
1352 | case SET_OF: | ||
1353 | render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act); | ||
1354 | render_opcode(out, "_jump_target(%u),\n", entry); | ||
1355 | break; | ||
1356 | } | ||
1357 | if (e->action) | ||
1358 | render_opcode(out, "_action(ACT_%s),\n", | ||
1359 | e->action->name); | ||
1360 | render_opcode(out, "ASN1_OP_RETURN,\n"); | ||
1361 | } | ||
1362 | } | ||
1363 | |||
1364 | /* | ||
1365 | * Render an element. | ||
1366 | */ | ||
1367 | static void render_element(FILE *out, struct element *e, struct element *tag) | ||
1368 | { | ||
1369 | struct element *ec; | ||
1370 | const char *cond, *act; | ||
1371 | int entry, skippable = 0, outofline = 0; | ||
1372 | |||
1373 | if (e->flags & ELEMENT_SKIPPABLE || | ||
1374 | (tag && tag->flags & ELEMENT_SKIPPABLE)) | ||
1375 | skippable = 1; | ||
1376 | |||
1377 | if ((e->type_def && e->type_def->ref_count > 1) || | ||
1378 | skippable) | ||
1379 | outofline = 1; | ||
1380 | |||
1381 | if (e->type_def && out) { | ||
1382 | render_more(out, "\t// %*.*s\n", | ||
1383 | (int)e->type_def->name->size, (int)e->type_def->name->size, | ||
1384 | e->type_def->name->value); | ||
1385 | } | ||
1386 | |||
1387 | /* Render the operation */ | ||
1388 | cond = (e->flags & ELEMENT_CONDITIONAL || | ||
1389 | (tag && tag->flags & ELEMENT_CONDITIONAL)) ? "COND_" : ""; | ||
1390 | act = e->action ? "_ACT" : ""; | ||
1391 | switch (e->compound) { | ||
1392 | case ANY: | ||
1393 | render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act); | ||
1394 | if (e->name) | ||
1395 | render_more(out, "\t\t// %*.*s", | ||
1396 | (int)e->name->size, (int)e->name->size, | ||
1397 | e->name->value); | ||
1398 | render_more(out, "\n"); | ||
1399 | goto dont_render_tag; | ||
1400 | |||
1401 | case TAG_OVERRIDE: | ||
1402 | render_element(out, e->children, e); | ||
1403 | return; | ||
1404 | |||
1405 | case SEQUENCE: | ||
1406 | case SEQUENCE_OF: | ||
1407 | case SET: | ||
1408 | case SET_OF: | ||
1409 | render_opcode(out, "ASN1_OP_%sMATCH%s%s,", | ||
1410 | cond, | ||
1411 | outofline ? "_JUMP" : "", | ||
1412 | skippable ? "_OR_SKIP" : ""); | ||
1413 | break; | ||
1414 | |||
1415 | case CHOICE: | ||
1416 | goto dont_render_tag; | ||
1417 | |||
1418 | case TYPE_REF: | ||
1419 | if (e->class == ASN1_UNIV && e->method == ASN1_PRIM && e->tag == 0) | ||
1420 | goto dont_render_tag; | ||
1421 | default: | ||
1422 | render_opcode(out, "ASN1_OP_%sMATCH%s%s,", | ||
1423 | cond, act, | ||
1424 | skippable ? "_OR_SKIP" : ""); | ||
1425 | break; | ||
1426 | } | ||
1427 | |||
1428 | if (e->name) | ||
1429 | render_more(out, "\t\t// %*.*s", | ||
1430 | (int)e->name->size, (int)e->name->size, | ||
1431 | e->name->value); | ||
1432 | render_more(out, "\n"); | ||
1433 | |||
1434 | /* Render the tag */ | ||
1435 | if (!tag) | ||
1436 | tag = e; | ||
1437 | if (tag->class == ASN1_UNIV && | ||
1438 | tag->tag != 14 && | ||
1439 | tag->tag != 15 && | ||
1440 | tag->tag != 31) | ||
1441 | render_opcode(out, "_tag(%s, %s, %s),\n", | ||
1442 | asn1_classes[tag->class], | ||
1443 | asn1_methods[tag->method | e->method], | ||
1444 | asn1_universal_tags[tag->tag]); | ||
1445 | else | ||
1446 | render_opcode(out, "_tagn(%s, %s, %2u),\n", | ||
1447 | asn1_classes[tag->class], | ||
1448 | asn1_methods[tag->method | e->method], | ||
1449 | tag->tag); | ||
1450 | tag = NULL; | ||
1451 | dont_render_tag: | ||
1452 | |||
1453 | /* Deal with compound types */ | ||
1454 | switch (e->compound) { | ||
1455 | case TYPE_REF: | ||
1456 | render_element(out, e->type->type->element, tag); | ||
1457 | if (e->action) | ||
1458 | render_opcode(out, "ASN1_OP_ACT,\n"); | ||
1459 | break; | ||
1460 | |||
1461 | case SEQUENCE: | ||
1462 | if (outofline) { | ||
1463 | /* Render out-of-line for multiple use or | ||
1464 | * skipability */ | ||
1465 | render_opcode(out, "_jump_target(%u),", e->entry_index); | ||
1466 | if (e->type_def && e->type_def->name) | ||
1467 | render_more(out, "\t\t// --> %*.*s", | ||
1468 | (int)e->type_def->name->size, | ||
1469 | (int)e->type_def->name->size, | ||
1470 | e->type_def->name->value); | ||
1471 | render_more(out, "\n"); | ||
1472 | if (!(e->flags & ELEMENT_RENDERED)) { | ||
1473 | e->flags |= ELEMENT_RENDERED; | ||
1474 | *render_list_p = e; | ||
1475 | render_list_p = &e->render_next; | ||
1476 | } | ||
1477 | return; | ||
1478 | } else { | ||
1479 | /* Render inline for single use */ | ||
1480 | render_depth++; | ||
1481 | for (ec = e->children; ec; ec = ec->next) | ||
1482 | render_element(out, ec, NULL); | ||
1483 | render_depth--; | ||
1484 | render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act); | ||
1485 | } | ||
1486 | break; | ||
1487 | |||
1488 | case SEQUENCE_OF: | ||
1489 | case SET_OF: | ||
1490 | if (outofline) { | ||
1491 | /* Render out-of-line for multiple use or | ||
1492 | * skipability */ | ||
1493 | render_opcode(out, "_jump_target(%u),", e->entry_index); | ||
1494 | if (e->type_def && e->type_def->name) | ||
1495 | render_more(out, "\t\t// --> %*.*s", | ||
1496 | (int)e->type_def->name->size, | ||
1497 | (int)e->type_def->name->size, | ||
1498 | e->type_def->name->value); | ||
1499 | render_more(out, "\n"); | ||
1500 | if (!(e->flags & ELEMENT_RENDERED)) { | ||
1501 | e->flags |= ELEMENT_RENDERED; | ||
1502 | *render_list_p = e; | ||
1503 | render_list_p = &e->render_next; | ||
1504 | } | ||
1505 | return; | ||
1506 | } else { | ||
1507 | /* Render inline for single use */ | ||
1508 | entry = nr_entries; | ||
1509 | render_depth++; | ||
1510 | render_element(out, e->children, NULL); | ||
1511 | render_depth--; | ||
1512 | if (e->compound == SEQUENCE_OF) | ||
1513 | render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act); | ||
1514 | else | ||
1515 | render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act); | ||
1516 | render_opcode(out, "_jump_target(%u),\n", entry); | ||
1517 | } | ||
1518 | break; | ||
1519 | |||
1520 | case SET: | ||
1521 | /* I can't think of a nice way to do SET support without having | ||
1522 | * a stack of bitmasks to make sure no element is repeated. | ||
1523 | * The bitmask has also to be checked that no non-optional | ||
1524 | * elements are left out whilst not preventing optional | ||
1525 | * elements from being left out. | ||
1526 | */ | ||
1527 | fprintf(stderr, "The ASN.1 SET type is not currently supported.\n"); | ||
1528 | exit(1); | ||
1529 | |||
1530 | case CHOICE: | ||
1531 | for (ec = e->children; ec; ec = ec->next) | ||
1532 | render_element(out, ec, NULL); | ||
1533 | if (!skippable) | ||
1534 | render_opcode(out, "ASN1_OP_COND_FAIL,\n"); | ||
1535 | if (e->action) | ||
1536 | render_opcode(out, "ASN1_OP_ACT,\n"); | ||
1537 | break; | ||
1538 | |||
1539 | default: | ||
1540 | break; | ||
1541 | } | ||
1542 | |||
1543 | if (e->action) | ||
1544 | render_opcode(out, "_action(ACT_%s),\n", e->action->name); | ||
1545 | } | ||
diff --git a/scripts/sign-file b/scripts/sign-file new file mode 100644 index 000000000000..e58e34e50ac5 --- /dev/null +++ b/scripts/sign-file | |||
@@ -0,0 +1,115 @@ | |||
1 | #!/bin/sh | ||
2 | # | ||
3 | # Sign a module file using the given key. | ||
4 | # | ||
5 | # Format: sign-file <key> <x509> <src-file> <dst-file> | ||
6 | # | ||
7 | |||
8 | scripts=`dirname $0` | ||
9 | |||
10 | CONFIG_MODULE_SIG_SHA512=y | ||
11 | if [ -r .config ] | ||
12 | then | ||
13 | . ./.config | ||
14 | fi | ||
15 | |||
16 | key="$1" | ||
17 | x509="$2" | ||
18 | src="$3" | ||
19 | dst="$4" | ||
20 | |||
21 | if [ ! -r "$key" ] | ||
22 | then | ||
23 | echo "Can't read private key" >&2 | ||
24 | exit 2 | ||
25 | fi | ||
26 | |||
27 | if [ ! -r "$x509" ] | ||
28 | then | ||
29 | echo "Can't read X.509 certificate" >&2 | ||
30 | exit 2 | ||
31 | fi | ||
32 | if [ ! -r "$x509.signer" ] | ||
33 | then | ||
34 | echo "Can't read Signer name" >&2 | ||
35 | exit 2; | ||
36 | fi | ||
37 | if [ ! -r "$x509.keyid" ] | ||
38 | then | ||
39 | echo "Can't read Key identifier" >&2 | ||
40 | exit 2; | ||
41 | fi | ||
42 | |||
43 | # | ||
44 | # Signature parameters | ||
45 | # | ||
46 | algo=1 # Public-key crypto algorithm: RSA | ||
47 | hash= # Digest algorithm | ||
48 | id_type=1 # Identifier type: X.509 | ||
49 | |||
50 | # | ||
51 | # Digest the data | ||
52 | # | ||
53 | dgst= | ||
54 | if [ "$CONFIG_MODULE_SIG_SHA1" = "y" ] | ||
55 | then | ||
56 | prologue="0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14" | ||
57 | dgst=-sha1 | ||
58 | hash=2 | ||
59 | elif [ "$CONFIG_MODULE_SIG_SHA224" = "y" ] | ||
60 | then | ||
61 | prologue="0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C" | ||
62 | dgst=-sha224 | ||
63 | hash=7 | ||
64 | elif [ "$CONFIG_MODULE_SIG_SHA256" = "y" ] | ||
65 | then | ||
66 | prologue="0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20" | ||
67 | dgst=-sha256 | ||
68 | hash=4 | ||
69 | elif [ "$CONFIG_MODULE_SIG_SHA384" = "y" ] | ||
70 | then | ||
71 | prologue="0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30" | ||
72 | dgst=-sha384 | ||
73 | hash=5 | ||
74 | elif [ "$CONFIG_MODULE_SIG_SHA512" = "y" ] | ||
75 | then | ||
76 | prologue="0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40" | ||
77 | dgst=-sha512 | ||
78 | hash=6 | ||
79 | else | ||
80 | echo "$0: Can't determine hash algorithm" >&2 | ||
81 | exit 2 | ||
82 | fi | ||
83 | |||
84 | ( | ||
85 | perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $? | ||
86 | openssl dgst $dgst -binary $src || exit $? | ||
87 | ) >$src.dig || exit $? | ||
88 | |||
89 | # | ||
90 | # Generate the binary signature, which will be just the integer that comprises | ||
91 | # the signature with no metadata attached. | ||
92 | # | ||
93 | openssl rsautl -sign -inkey $key -keyform PEM -in $src.dig -out $src.sig || exit $? | ||
94 | signerlen=`stat -c %s $x509.signer` | ||
95 | keyidlen=`stat -c %s $x509.keyid` | ||
96 | siglen=`stat -c %s $src.sig` | ||
97 | |||
98 | # | ||
99 | # Build the signed binary | ||
100 | # | ||
101 | ( | ||
102 | cat $src || exit $? | ||
103 | echo '~Module signature appended~' || exit $? | ||
104 | cat $x509.signer $x509.keyid || exit $? | ||
105 | |||
106 | # Preface each signature integer with a 2-byte BE length | ||
107 | perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $? | ||
108 | cat $src.sig || exit $? | ||
109 | |||
110 | # Generate the information block | ||
111 | perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $? | ||
112 | ) >$dst~ || exit $? | ||
113 | |||
114 | # Permit in-place signing | ||
115 | mv $dst~ $dst || exit $? | ||
diff --git a/scripts/x509keyid b/scripts/x509keyid new file mode 100755 index 000000000000..c8e91a4af385 --- /dev/null +++ b/scripts/x509keyid | |||
@@ -0,0 +1,268 @@ | |||
1 | #!/usr/bin/perl -w | ||
2 | # | ||
3 | # Generate an identifier from an X.509 certificate that can be placed in a | ||
4 | # module signature to indentify the key to use. | ||
5 | # | ||
6 | # Format: | ||
7 | # | ||
8 | # ./scripts/x509keyid <x509-cert> <signer's-name> <key-id> | ||
9 | # | ||
10 | # We read the DER-encoded X509 certificate and parse it to extract the Subject | ||
11 | # name and Subject Key Identifier. The provide the data we need to build the | ||
12 | # certificate identifier. | ||
13 | # | ||
14 | # The signer's name part of the identifier is fabricated from the commonName, | ||
15 | # the organizationName or the emailAddress components of the X.509 subject | ||
16 | # name and written to the second named file. | ||
17 | # | ||
18 | # The subject key ID to select which of that signer's certificates we're | ||
19 | # intending to use to sign the module is written to the third named file. | ||
20 | # | ||
21 | use strict; | ||
22 | |||
23 | my $raw_data; | ||
24 | |||
25 | die "Need three filenames\n" if ($#ARGV != 2); | ||
26 | |||
27 | my $src = $ARGV[0]; | ||
28 | |||
29 | open(FD, "<$src") || die $src; | ||
30 | binmode FD; | ||
31 | my @st = stat(FD); | ||
32 | die $src if (!@st); | ||
33 | read(FD, $raw_data, $st[7]) || die $src; | ||
34 | close(FD); | ||
35 | |||
36 | my $UNIV = 0 << 6; | ||
37 | my $APPL = 1 << 6; | ||
38 | my $CONT = 2 << 6; | ||
39 | my $PRIV = 3 << 6; | ||
40 | |||
41 | my $CONS = 0x20; | ||
42 | |||
43 | my $BOOLEAN = 0x01; | ||
44 | my $INTEGER = 0x02; | ||
45 | my $BIT_STRING = 0x03; | ||
46 | my $OCTET_STRING = 0x04; | ||
47 | my $NULL = 0x05; | ||
48 | my $OBJ_ID = 0x06; | ||
49 | my $UTF8String = 0x0c; | ||
50 | my $SEQUENCE = 0x10; | ||
51 | my $SET = 0x11; | ||
52 | my $UTCTime = 0x17; | ||
53 | my $GeneralizedTime = 0x18; | ||
54 | |||
55 | my %OIDs = ( | ||
56 | pack("CCC", 85, 4, 3) => "commonName", | ||
57 | pack("CCC", 85, 4, 6) => "countryName", | ||
58 | pack("CCC", 85, 4, 10) => "organizationName", | ||
59 | pack("CCC", 85, 4, 11) => "organizationUnitName", | ||
60 | pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption", | ||
61 | pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption", | ||
62 | pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress", | ||
63 | pack("CCC", 85, 29, 35) => "authorityKeyIdentifier", | ||
64 | pack("CCC", 85, 29, 14) => "subjectKeyIdentifier", | ||
65 | pack("CCC", 85, 29, 19) => "basicConstraints" | ||
66 | ); | ||
67 | |||
68 | ############################################################################### | ||
69 | # | ||
70 | # Extract an ASN.1 element from a string and return information about it. | ||
71 | # | ||
72 | ############################################################################### | ||
73 | sub asn1_extract($$@) | ||
74 | { | ||
75 | my ($cursor, $expected_tag, $optional) = @_; | ||
76 | |||
77 | return [ -1 ] | ||
78 | if ($cursor->[1] == 0 && $optional); | ||
79 | |||
80 | die $src, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n" | ||
81 | if ($cursor->[1] < 2); | ||
82 | |||
83 | my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2)); | ||
84 | |||
85 | if ($expected_tag != -1 && $tag != $expected_tag) { | ||
86 | return [ -1 ] | ||
87 | if ($optional); | ||
88 | die $src, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag, | ||
89 | " not ", $expected_tag, ")\n"; | ||
90 | } | ||
91 | |||
92 | $cursor->[0] += 2; | ||
93 | $cursor->[1] -= 2; | ||
94 | |||
95 | die $src, ": ", $cursor->[0], ": ASN.1 long tag\n" | ||
96 | if (($tag & 0x1f) == 0x1f); | ||
97 | die $src, ": ", $cursor->[0], ": ASN.1 indefinite length\n" | ||
98 | if ($len == 0x80); | ||
99 | |||
100 | if ($len > 0x80) { | ||
101 | my $l = $len - 0x80; | ||
102 | die $src, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n" | ||
103 | if ($cursor->[1] < $l); | ||
104 | |||
105 | if ($l == 0x1) { | ||
106 | $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)); | ||
107 | } elsif ($l = 0x2) { | ||
108 | $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2)); | ||
109 | } elsif ($l = 0x3) { | ||
110 | $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16; | ||
111 | $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2)); | ||
112 | } elsif ($l = 0x4) { | ||
113 | $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4)); | ||
114 | } else { | ||
115 | die $src, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n"; | ||
116 | } | ||
117 | |||
118 | $cursor->[0] += $l; | ||
119 | $cursor->[1] -= $l; | ||
120 | } | ||
121 | |||
122 | die $src, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n" | ||
123 | if ($cursor->[1] < $len); | ||
124 | |||
125 | my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ]; | ||
126 | $cursor->[0] += $len; | ||
127 | $cursor->[1] -= $len; | ||
128 | |||
129 | return $ret; | ||
130 | } | ||
131 | |||
132 | ############################################################################### | ||
133 | # | ||
134 | # Retrieve the data referred to by a cursor | ||
135 | # | ||
136 | ############################################################################### | ||
137 | sub asn1_retrieve($) | ||
138 | { | ||
139 | my ($cursor) = @_; | ||
140 | my ($offset, $len, $data) = @$cursor; | ||
141 | return substr($$data, $offset, $len); | ||
142 | } | ||
143 | |||
144 | ############################################################################### | ||
145 | # | ||
146 | # Roughly parse the X.509 certificate | ||
147 | # | ||
148 | ############################################################################### | ||
149 | my $cursor = [ 0, length($raw_data), \$raw_data ]; | ||
150 | |||
151 | my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE); | ||
152 | my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE); | ||
153 | my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1); | ||
154 | my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER); | ||
155 | my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); | ||
156 | my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); | ||
157 | my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); | ||
158 | my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); | ||
159 | my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE); | ||
160 | my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1); | ||
161 | my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1); | ||
162 | my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1); | ||
163 | |||
164 | my $subject_key_id = (); | ||
165 | my $authority_key_id = (); | ||
166 | |||
167 | # | ||
168 | # Parse the extension list | ||
169 | # | ||
170 | if ($extension_list->[0] != -1) { | ||
171 | my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE); | ||
172 | |||
173 | while ($extensions->[1]->[1] > 0) { | ||
174 | my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE); | ||
175 | my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID); | ||
176 | my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1); | ||
177 | my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING); | ||
178 | |||
179 | my $raw_oid = asn1_retrieve($x_oid->[1]); | ||
180 | next if (!exists($OIDs{$raw_oid})); | ||
181 | my $x_type = $OIDs{$raw_oid}; | ||
182 | |||
183 | my $raw_value = asn1_retrieve($x_val->[1]); | ||
184 | |||
185 | if ($x_type eq "subjectKeyIdentifier") { | ||
186 | my $vcursor = [ 0, length($raw_value), \$raw_value ]; | ||
187 | |||
188 | $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING); | ||
189 | } | ||
190 | } | ||
191 | } | ||
192 | |||
193 | ############################################################################### | ||
194 | # | ||
195 | # Determine what we're going to use as the signer's name. In order of | ||
196 | # preference, take one of: commonName, organizationName or emailAddress. | ||
197 | # | ||
198 | ############################################################################### | ||
199 | my $org = ""; | ||
200 | my $cn = ""; | ||
201 | my $email = ""; | ||
202 | |||
203 | while ($subject->[1]->[1] > 0) { | ||
204 | my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET); | ||
205 | my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE); | ||
206 | my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID); | ||
207 | my $n_val = asn1_extract($attr->[1], -1); | ||
208 | |||
209 | my $raw_oid = asn1_retrieve($n_oid->[1]); | ||
210 | next if (!exists($OIDs{$raw_oid})); | ||
211 | my $n_type = $OIDs{$raw_oid}; | ||
212 | |||
213 | my $raw_value = asn1_retrieve($n_val->[1]); | ||
214 | |||
215 | if ($n_type eq "organizationName") { | ||
216 | $org = $raw_value; | ||
217 | } elsif ($n_type eq "commonName") { | ||
218 | $cn = $raw_value; | ||
219 | } elsif ($n_type eq "emailAddress") { | ||
220 | $email = $raw_value; | ||
221 | } | ||
222 | } | ||
223 | |||
224 | my $id_name = $email; | ||
225 | |||
226 | if ($org && $cn) { | ||
227 | # Don't use the organizationName if the commonName repeats it | ||
228 | if (length($org) <= length($cn) && | ||
229 | substr($cn, 0, length($org)) eq $org) { | ||
230 | $id_name = $cn; | ||
231 | goto got_id_name; | ||
232 | } | ||
233 | |||
234 | # Or a signifcant chunk of it | ||
235 | if (length($org) >= 7 && | ||
236 | length($cn) >= 7 && | ||
237 | substr($cn, 0, 7) eq substr($org, 0, 7)) { | ||
238 | $id_name = $cn; | ||
239 | goto got_id_name; | ||
240 | } | ||
241 | |||
242 | $id_name = $org . ": " . $cn; | ||
243 | } elsif ($org) { | ||
244 | $id_name = $org; | ||
245 | } elsif ($cn) { | ||
246 | $id_name = $cn; | ||
247 | } | ||
248 | |||
249 | got_id_name: | ||
250 | |||
251 | ############################################################################### | ||
252 | # | ||
253 | # Output the signer's name and the key identifier that we're going to include | ||
254 | # in module signatures. | ||
255 | # | ||
256 | ############################################################################### | ||
257 | die $src, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n" | ||
258 | if (!$subject_key_id); | ||
259 | |||
260 | my $id_key_id = asn1_retrieve($subject_key_id->[1]); | ||
261 | |||
262 | open(OUTFD, ">$ARGV[1]") || die $ARGV[1]; | ||
263 | print OUTFD $id_name; | ||
264 | close OUTFD || die $ARGV[1]; | ||
265 | |||
266 | open(OUTFD, ">$ARGV[2]") || die $ARGV[2]; | ||
267 | print OUTFD $id_key_id; | ||
268 | close OUTFD || die $ARGV[2]; | ||
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 2d1bb8af7696..9e1e005c7596 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c | |||
@@ -773,8 +773,8 @@ static int encrypted_init(struct encrypted_key_payload *epayload, | |||
773 | * | 773 | * |
774 | * On success, return 0. Otherwise return errno. | 774 | * On success, return 0. Otherwise return errno. |
775 | */ | 775 | */ |
776 | static int encrypted_instantiate(struct key *key, const void *data, | 776 | static int encrypted_instantiate(struct key *key, |
777 | size_t datalen) | 777 | struct key_preparsed_payload *prep) |
778 | { | 778 | { |
779 | struct encrypted_key_payload *epayload = NULL; | 779 | struct encrypted_key_payload *epayload = NULL; |
780 | char *datablob = NULL; | 780 | char *datablob = NULL; |
@@ -782,16 +782,17 @@ static int encrypted_instantiate(struct key *key, const void *data, | |||
782 | char *master_desc = NULL; | 782 | char *master_desc = NULL; |
783 | char *decrypted_datalen = NULL; | 783 | char *decrypted_datalen = NULL; |
784 | char *hex_encoded_iv = NULL; | 784 | char *hex_encoded_iv = NULL; |
785 | size_t datalen = prep->datalen; | ||
785 | int ret; | 786 | int ret; |
786 | 787 | ||
787 | if (datalen <= 0 || datalen > 32767 || !data) | 788 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
788 | return -EINVAL; | 789 | return -EINVAL; |
789 | 790 | ||
790 | datablob = kmalloc(datalen + 1, GFP_KERNEL); | 791 | datablob = kmalloc(datalen + 1, GFP_KERNEL); |
791 | if (!datablob) | 792 | if (!datablob) |
792 | return -ENOMEM; | 793 | return -ENOMEM; |
793 | datablob[datalen] = 0; | 794 | datablob[datalen] = 0; |
794 | memcpy(datablob, data, datalen); | 795 | memcpy(datablob, prep->data, datalen); |
795 | ret = datablob_parse(datablob, &format, &master_desc, | 796 | ret = datablob_parse(datablob, &format, &master_desc, |
796 | &decrypted_datalen, &hex_encoded_iv); | 797 | &decrypted_datalen, &hex_encoded_iv); |
797 | if (ret < 0) | 798 | if (ret < 0) |
@@ -834,16 +835,17 @@ static void encrypted_rcu_free(struct rcu_head *rcu) | |||
834 | * | 835 | * |
835 | * On success, return 0. Otherwise return errno. | 836 | * On success, return 0. Otherwise return errno. |
836 | */ | 837 | */ |
837 | static int encrypted_update(struct key *key, const void *data, size_t datalen) | 838 | static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) |
838 | { | 839 | { |
839 | struct encrypted_key_payload *epayload = key->payload.data; | 840 | struct encrypted_key_payload *epayload = key->payload.data; |
840 | struct encrypted_key_payload *new_epayload; | 841 | struct encrypted_key_payload *new_epayload; |
841 | char *buf; | 842 | char *buf; |
842 | char *new_master_desc = NULL; | 843 | char *new_master_desc = NULL; |
843 | const char *format = NULL; | 844 | const char *format = NULL; |
845 | size_t datalen = prep->datalen; | ||
844 | int ret = 0; | 846 | int ret = 0; |
845 | 847 | ||
846 | if (datalen <= 0 || datalen > 32767 || !data) | 848 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
847 | return -EINVAL; | 849 | return -EINVAL; |
848 | 850 | ||
849 | buf = kmalloc(datalen + 1, GFP_KERNEL); | 851 | buf = kmalloc(datalen + 1, GFP_KERNEL); |
@@ -851,7 +853,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen) | |||
851 | return -ENOMEM; | 853 | return -ENOMEM; |
852 | 854 | ||
853 | buf[datalen] = 0; | 855 | buf[datalen] = 0; |
854 | memcpy(buf, data, datalen); | 856 | memcpy(buf, prep->data, datalen); |
855 | ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL); | 857 | ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL); |
856 | if (ret < 0) | 858 | if (ret < 0) |
857 | goto out; | 859 | goto out; |
diff --git a/security/keys/key.c b/security/keys/key.c index a30e92734905..a15c9da8f971 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -405,8 +405,7 @@ EXPORT_SYMBOL(key_payload_reserve); | |||
405 | * key_construction_mutex. | 405 | * key_construction_mutex. |
406 | */ | 406 | */ |
407 | static int __key_instantiate_and_link(struct key *key, | 407 | static int __key_instantiate_and_link(struct key *key, |
408 | const void *data, | 408 | struct key_preparsed_payload *prep, |
409 | size_t datalen, | ||
410 | struct key *keyring, | 409 | struct key *keyring, |
411 | struct key *authkey, | 410 | struct key *authkey, |
412 | unsigned long *_prealloc) | 411 | unsigned long *_prealloc) |
@@ -424,7 +423,7 @@ static int __key_instantiate_and_link(struct key *key, | |||
424 | /* can't instantiate twice */ | 423 | /* can't instantiate twice */ |
425 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { | 424 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { |
426 | /* instantiate the key */ | 425 | /* instantiate the key */ |
427 | ret = key->type->instantiate(key, data, datalen); | 426 | ret = key->type->instantiate(key, prep); |
428 | 427 | ||
429 | if (ret == 0) { | 428 | if (ret == 0) { |
430 | /* mark the key as being instantiated */ | 429 | /* mark the key as being instantiated */ |
@@ -475,22 +474,37 @@ int key_instantiate_and_link(struct key *key, | |||
475 | struct key *keyring, | 474 | struct key *keyring, |
476 | struct key *authkey) | 475 | struct key *authkey) |
477 | { | 476 | { |
477 | struct key_preparsed_payload prep; | ||
478 | unsigned long prealloc; | 478 | unsigned long prealloc; |
479 | int ret; | 479 | int ret; |
480 | 480 | ||
481 | memset(&prep, 0, sizeof(prep)); | ||
482 | prep.data = data; | ||
483 | prep.datalen = datalen; | ||
484 | prep.quotalen = key->type->def_datalen; | ||
485 | if (key->type->preparse) { | ||
486 | ret = key->type->preparse(&prep); | ||
487 | if (ret < 0) | ||
488 | goto error; | ||
489 | } | ||
490 | |||
481 | if (keyring) { | 491 | if (keyring) { |
482 | ret = __key_link_begin(keyring, key->type, key->description, | 492 | ret = __key_link_begin(keyring, key->type, key->description, |
483 | &prealloc); | 493 | &prealloc); |
484 | if (ret < 0) | 494 | if (ret < 0) |
485 | return ret; | 495 | goto error_free_preparse; |
486 | } | 496 | } |
487 | 497 | ||
488 | ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey, | 498 | ret = __key_instantiate_and_link(key, &prep, keyring, authkey, |
489 | &prealloc); | 499 | &prealloc); |
490 | 500 | ||
491 | if (keyring) | 501 | if (keyring) |
492 | __key_link_end(keyring, key->type, prealloc); | 502 | __key_link_end(keyring, key->type, prealloc); |
493 | 503 | ||
504 | error_free_preparse: | ||
505 | if (key->type->preparse) | ||
506 | key->type->free_preparse(&prep); | ||
507 | error: | ||
494 | return ret; | 508 | return ret; |
495 | } | 509 | } |
496 | 510 | ||
@@ -699,7 +713,7 @@ void key_type_put(struct key_type *ktype) | |||
699 | * if we get an error. | 713 | * if we get an error. |
700 | */ | 714 | */ |
701 | static inline key_ref_t __key_update(key_ref_t key_ref, | 715 | static inline key_ref_t __key_update(key_ref_t key_ref, |
702 | const void *payload, size_t plen) | 716 | struct key_preparsed_payload *prep) |
703 | { | 717 | { |
704 | struct key *key = key_ref_to_ptr(key_ref); | 718 | struct key *key = key_ref_to_ptr(key_ref); |
705 | int ret; | 719 | int ret; |
@@ -715,7 +729,7 @@ static inline key_ref_t __key_update(key_ref_t key_ref, | |||
715 | 729 | ||
716 | down_write(&key->sem); | 730 | down_write(&key->sem); |
717 | 731 | ||
718 | ret = key->type->update(key, payload, plen); | 732 | ret = key->type->update(key, prep); |
719 | if (ret == 0) | 733 | if (ret == 0) |
720 | /* updating a negative key instantiates it */ | 734 | /* updating a negative key instantiates it */ |
721 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); | 735 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); |
@@ -767,6 +781,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
767 | unsigned long flags) | 781 | unsigned long flags) |
768 | { | 782 | { |
769 | unsigned long prealloc; | 783 | unsigned long prealloc; |
784 | struct key_preparsed_payload prep; | ||
770 | const struct cred *cred = current_cred(); | 785 | const struct cred *cred = current_cred(); |
771 | struct key_type *ktype; | 786 | struct key_type *ktype; |
772 | struct key *keyring, *key = NULL; | 787 | struct key *keyring, *key = NULL; |
@@ -782,8 +797,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
782 | } | 797 | } |
783 | 798 | ||
784 | key_ref = ERR_PTR(-EINVAL); | 799 | key_ref = ERR_PTR(-EINVAL); |
785 | if (!ktype->match || !ktype->instantiate) | 800 | if (!ktype->match || !ktype->instantiate || |
786 | goto error_2; | 801 | (!description && !ktype->preparse)) |
802 | goto error_put_type; | ||
787 | 803 | ||
788 | keyring = key_ref_to_ptr(keyring_ref); | 804 | keyring = key_ref_to_ptr(keyring_ref); |
789 | 805 | ||
@@ -791,18 +807,37 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
791 | 807 | ||
792 | key_ref = ERR_PTR(-ENOTDIR); | 808 | key_ref = ERR_PTR(-ENOTDIR); |
793 | if (keyring->type != &key_type_keyring) | 809 | if (keyring->type != &key_type_keyring) |
794 | goto error_2; | 810 | goto error_put_type; |
811 | |||
812 | memset(&prep, 0, sizeof(prep)); | ||
813 | prep.data = payload; | ||
814 | prep.datalen = plen; | ||
815 | prep.quotalen = ktype->def_datalen; | ||
816 | if (ktype->preparse) { | ||
817 | ret = ktype->preparse(&prep); | ||
818 | if (ret < 0) { | ||
819 | key_ref = ERR_PTR(ret); | ||
820 | goto error_put_type; | ||
821 | } | ||
822 | if (!description) | ||
823 | description = prep.description; | ||
824 | key_ref = ERR_PTR(-EINVAL); | ||
825 | if (!description) | ||
826 | goto error_free_prep; | ||
827 | } | ||
795 | 828 | ||
796 | ret = __key_link_begin(keyring, ktype, description, &prealloc); | 829 | ret = __key_link_begin(keyring, ktype, description, &prealloc); |
797 | if (ret < 0) | 830 | if (ret < 0) { |
798 | goto error_2; | 831 | key_ref = ERR_PTR(ret); |
832 | goto error_free_prep; | ||
833 | } | ||
799 | 834 | ||
800 | /* if we're going to allocate a new key, we're going to have | 835 | /* if we're going to allocate a new key, we're going to have |
801 | * to modify the keyring */ | 836 | * to modify the keyring */ |
802 | ret = key_permission(keyring_ref, KEY_WRITE); | 837 | ret = key_permission(keyring_ref, KEY_WRITE); |
803 | if (ret < 0) { | 838 | if (ret < 0) { |
804 | key_ref = ERR_PTR(ret); | 839 | key_ref = ERR_PTR(ret); |
805 | goto error_3; | 840 | goto error_link_end; |
806 | } | 841 | } |
807 | 842 | ||
808 | /* if it's possible to update this type of key, search for an existing | 843 | /* if it's possible to update this type of key, search for an existing |
@@ -833,25 +868,27 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
833 | perm, flags); | 868 | perm, flags); |
834 | if (IS_ERR(key)) { | 869 | if (IS_ERR(key)) { |
835 | key_ref = ERR_CAST(key); | 870 | key_ref = ERR_CAST(key); |
836 | goto error_3; | 871 | goto error_link_end; |
837 | } | 872 | } |
838 | 873 | ||
839 | /* instantiate it and link it into the target keyring */ | 874 | /* instantiate it and link it into the target keyring */ |
840 | ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL, | 875 | ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &prealloc); |
841 | &prealloc); | ||
842 | if (ret < 0) { | 876 | if (ret < 0) { |
843 | key_put(key); | 877 | key_put(key); |
844 | key_ref = ERR_PTR(ret); | 878 | key_ref = ERR_PTR(ret); |
845 | goto error_3; | 879 | goto error_link_end; |
846 | } | 880 | } |
847 | 881 | ||
848 | key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); | 882 | key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); |
849 | 883 | ||
850 | error_3: | 884 | error_link_end: |
851 | __key_link_end(keyring, ktype, prealloc); | 885 | __key_link_end(keyring, ktype, prealloc); |
852 | error_2: | 886 | error_free_prep: |
887 | if (ktype->preparse) | ||
888 | ktype->free_preparse(&prep); | ||
889 | error_put_type: | ||
853 | key_type_put(ktype); | 890 | key_type_put(ktype); |
854 | error: | 891 | error: |
855 | return key_ref; | 892 | return key_ref; |
856 | 893 | ||
857 | found_matching_key: | 894 | found_matching_key: |
@@ -859,10 +896,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
859 | * - we can drop the locks first as we have the key pinned | 896 | * - we can drop the locks first as we have the key pinned |
860 | */ | 897 | */ |
861 | __key_link_end(keyring, ktype, prealloc); | 898 | __key_link_end(keyring, ktype, prealloc); |
862 | key_type_put(ktype); | ||
863 | 899 | ||
864 | key_ref = __key_update(key_ref, payload, plen); | 900 | key_ref = __key_update(key_ref, &prep); |
865 | goto error; | 901 | goto error_free_prep; |
866 | } | 902 | } |
867 | EXPORT_SYMBOL(key_create_or_update); | 903 | EXPORT_SYMBOL(key_create_or_update); |
868 | 904 | ||
@@ -881,6 +917,7 @@ EXPORT_SYMBOL(key_create_or_update); | |||
881 | */ | 917 | */ |
882 | int key_update(key_ref_t key_ref, const void *payload, size_t plen) | 918 | int key_update(key_ref_t key_ref, const void *payload, size_t plen) |
883 | { | 919 | { |
920 | struct key_preparsed_payload prep; | ||
884 | struct key *key = key_ref_to_ptr(key_ref); | 921 | struct key *key = key_ref_to_ptr(key_ref); |
885 | int ret; | 922 | int ret; |
886 | 923 | ||
@@ -893,18 +930,31 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) | |||
893 | 930 | ||
894 | /* attempt to update it if supported */ | 931 | /* attempt to update it if supported */ |
895 | ret = -EOPNOTSUPP; | 932 | ret = -EOPNOTSUPP; |
896 | if (key->type->update) { | 933 | if (!key->type->update) |
897 | down_write(&key->sem); | 934 | goto error; |
898 | |||
899 | ret = key->type->update(key, payload, plen); | ||
900 | if (ret == 0) | ||
901 | /* updating a negative key instantiates it */ | ||
902 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); | ||
903 | 935 | ||
904 | up_write(&key->sem); | 936 | memset(&prep, 0, sizeof(prep)); |
937 | prep.data = payload; | ||
938 | prep.datalen = plen; | ||
939 | prep.quotalen = key->type->def_datalen; | ||
940 | if (key->type->preparse) { | ||
941 | ret = key->type->preparse(&prep); | ||
942 | if (ret < 0) | ||
943 | goto error; | ||
905 | } | 944 | } |
906 | 945 | ||
907 | error: | 946 | down_write(&key->sem); |
947 | |||
948 | ret = key->type->update(key, &prep); | ||
949 | if (ret == 0) | ||
950 | /* updating a negative key instantiates it */ | ||
951 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); | ||
952 | |||
953 | up_write(&key->sem); | ||
954 | |||
955 | if (key->type->preparse) | ||
956 | key->type->free_preparse(&prep); | ||
957 | error: | ||
908 | return ret; | 958 | return ret; |
909 | } | 959 | } |
910 | EXPORT_SYMBOL(key_update); | 960 | EXPORT_SYMBOL(key_update); |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 305ecb76519c..5d34b4e827d6 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -46,6 +46,9 @@ static int key_get_type_from_user(char *type, | |||
46 | * Extract the description of a new key from userspace and either add it as a | 46 | * Extract the description of a new key from userspace and either add it as a |
47 | * new key to the specified keyring or update a matching key in that keyring. | 47 | * new key to the specified keyring or update a matching key in that keyring. |
48 | * | 48 | * |
49 | * If the description is NULL or an empty string, the key type is asked to | ||
50 | * generate one from the payload. | ||
51 | * | ||
49 | * The keyring must be writable so that we can attach the key to it. | 52 | * The keyring must be writable so that we can attach the key to it. |
50 | * | 53 | * |
51 | * If successful, the new key's serial number is returned, otherwise an error | 54 | * If successful, the new key's serial number is returned, otherwise an error |
@@ -72,10 +75,17 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, | |||
72 | if (ret < 0) | 75 | if (ret < 0) |
73 | goto error; | 76 | goto error; |
74 | 77 | ||
75 | description = strndup_user(_description, PAGE_SIZE); | 78 | description = NULL; |
76 | if (IS_ERR(description)) { | 79 | if (_description) { |
77 | ret = PTR_ERR(description); | 80 | description = strndup_user(_description, PAGE_SIZE); |
78 | goto error; | 81 | if (IS_ERR(description)) { |
82 | ret = PTR_ERR(description); | ||
83 | goto error; | ||
84 | } | ||
85 | if (!*description) { | ||
86 | kfree(description); | ||
87 | description = NULL; | ||
88 | } | ||
79 | } | 89 | } |
80 | 90 | ||
81 | /* pull the payload in if one was supplied */ | 91 | /* pull the payload in if one was supplied */ |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index a5f5c4b6edc5..6e42df15a24c 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -66,7 +66,7 @@ static inline unsigned keyring_hash(const char *desc) | |||
66 | * operations. | 66 | * operations. |
67 | */ | 67 | */ |
68 | static int keyring_instantiate(struct key *keyring, | 68 | static int keyring_instantiate(struct key *keyring, |
69 | const void *data, size_t datalen); | 69 | struct key_preparsed_payload *prep); |
70 | static int keyring_match(const struct key *keyring, const void *criterion); | 70 | static int keyring_match(const struct key *keyring, const void *criterion); |
71 | static void keyring_revoke(struct key *keyring); | 71 | static void keyring_revoke(struct key *keyring); |
72 | static void keyring_destroy(struct key *keyring); | 72 | static void keyring_destroy(struct key *keyring); |
@@ -121,12 +121,12 @@ static void keyring_publish_name(struct key *keyring) | |||
121 | * Returns 0 on success, -EINVAL if given any data. | 121 | * Returns 0 on success, -EINVAL if given any data. |
122 | */ | 122 | */ |
123 | static int keyring_instantiate(struct key *keyring, | 123 | static int keyring_instantiate(struct key *keyring, |
124 | const void *data, size_t datalen) | 124 | struct key_preparsed_payload *prep) |
125 | { | 125 | { |
126 | int ret; | 126 | int ret; |
127 | 127 | ||
128 | ret = -EINVAL; | 128 | ret = -EINVAL; |
129 | if (datalen == 0) { | 129 | if (prep->datalen == 0) { |
130 | /* make the keyring available by name if it has one */ | 130 | /* make the keyring available by name if it has one */ |
131 | keyring_publish_name(keyring); | 131 | keyring_publish_name(keyring); |
132 | ret = 0; | 132 | ret = 0; |
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 60d4e3f5e4bb..85730d5a5a59 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
@@ -19,7 +19,8 @@ | |||
19 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
20 | #include "internal.h" | 20 | #include "internal.h" |
21 | 21 | ||
22 | static int request_key_auth_instantiate(struct key *, const void *, size_t); | 22 | static int request_key_auth_instantiate(struct key *, |
23 | struct key_preparsed_payload *); | ||
23 | static void request_key_auth_describe(const struct key *, struct seq_file *); | 24 | static void request_key_auth_describe(const struct key *, struct seq_file *); |
24 | static void request_key_auth_revoke(struct key *); | 25 | static void request_key_auth_revoke(struct key *); |
25 | static void request_key_auth_destroy(struct key *); | 26 | static void request_key_auth_destroy(struct key *); |
@@ -42,10 +43,9 @@ struct key_type key_type_request_key_auth = { | |||
42 | * Instantiate a request-key authorisation key. | 43 | * Instantiate a request-key authorisation key. |
43 | */ | 44 | */ |
44 | static int request_key_auth_instantiate(struct key *key, | 45 | static int request_key_auth_instantiate(struct key *key, |
45 | const void *data, | 46 | struct key_preparsed_payload *prep) |
46 | size_t datalen) | ||
47 | { | 47 | { |
48 | key->payload.data = (struct request_key_auth *) data; | 48 | key->payload.data = (struct request_key_auth *)prep->data; |
49 | return 0; | 49 | return 0; |
50 | } | 50 | } |
51 | 51 | ||
diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 3f163d0489ad..e13fcf7636f7 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c | |||
@@ -895,23 +895,24 @@ static struct trusted_key_payload *trusted_payload_alloc(struct key *key) | |||
895 | * | 895 | * |
896 | * On success, return 0. Otherwise return errno. | 896 | * On success, return 0. Otherwise return errno. |
897 | */ | 897 | */ |
898 | static int trusted_instantiate(struct key *key, const void *data, | 898 | static int trusted_instantiate(struct key *key, |
899 | size_t datalen) | 899 | struct key_preparsed_payload *prep) |
900 | { | 900 | { |
901 | struct trusted_key_payload *payload = NULL; | 901 | struct trusted_key_payload *payload = NULL; |
902 | struct trusted_key_options *options = NULL; | 902 | struct trusted_key_options *options = NULL; |
903 | size_t datalen = prep->datalen; | ||
903 | char *datablob; | 904 | char *datablob; |
904 | int ret = 0; | 905 | int ret = 0; |
905 | int key_cmd; | 906 | int key_cmd; |
906 | size_t key_len; | 907 | size_t key_len; |
907 | 908 | ||
908 | if (datalen <= 0 || datalen > 32767 || !data) | 909 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
909 | return -EINVAL; | 910 | return -EINVAL; |
910 | 911 | ||
911 | datablob = kmalloc(datalen + 1, GFP_KERNEL); | 912 | datablob = kmalloc(datalen + 1, GFP_KERNEL); |
912 | if (!datablob) | 913 | if (!datablob) |
913 | return -ENOMEM; | 914 | return -ENOMEM; |
914 | memcpy(datablob, data, datalen); | 915 | memcpy(datablob, prep->data, datalen); |
915 | datablob[datalen] = '\0'; | 916 | datablob[datalen] = '\0'; |
916 | 917 | ||
917 | options = trusted_options_alloc(); | 918 | options = trusted_options_alloc(); |
@@ -981,17 +982,18 @@ static void trusted_rcu_free(struct rcu_head *rcu) | |||
981 | /* | 982 | /* |
982 | * trusted_update - reseal an existing key with new PCR values | 983 | * trusted_update - reseal an existing key with new PCR values |
983 | */ | 984 | */ |
984 | static int trusted_update(struct key *key, const void *data, size_t datalen) | 985 | static int trusted_update(struct key *key, struct key_preparsed_payload *prep) |
985 | { | 986 | { |
986 | struct trusted_key_payload *p = key->payload.data; | 987 | struct trusted_key_payload *p = key->payload.data; |
987 | struct trusted_key_payload *new_p; | 988 | struct trusted_key_payload *new_p; |
988 | struct trusted_key_options *new_o; | 989 | struct trusted_key_options *new_o; |
990 | size_t datalen = prep->datalen; | ||
989 | char *datablob; | 991 | char *datablob; |
990 | int ret = 0; | 992 | int ret = 0; |
991 | 993 | ||
992 | if (!p->migratable) | 994 | if (!p->migratable) |
993 | return -EPERM; | 995 | return -EPERM; |
994 | if (datalen <= 0 || datalen > 32767 || !data) | 996 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
995 | return -EINVAL; | 997 | return -EINVAL; |
996 | 998 | ||
997 | datablob = kmalloc(datalen + 1, GFP_KERNEL); | 999 | datablob = kmalloc(datalen + 1, GFP_KERNEL); |
@@ -1008,7 +1010,7 @@ static int trusted_update(struct key *key, const void *data, size_t datalen) | |||
1008 | goto out; | 1010 | goto out; |
1009 | } | 1011 | } |
1010 | 1012 | ||
1011 | memcpy(datablob, data, datalen); | 1013 | memcpy(datablob, prep->data, datalen); |
1012 | datablob[datalen] = '\0'; | 1014 | datablob[datalen] = '\0'; |
1013 | ret = datablob_parse(datablob, new_p, new_o); | 1015 | ret = datablob_parse(datablob, new_p, new_o); |
1014 | if (ret != Opt_update) { | 1016 | if (ret != Opt_update) { |
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index c7660a25a3e4..55dc88939185 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c | |||
@@ -58,13 +58,14 @@ EXPORT_SYMBOL_GPL(key_type_logon); | |||
58 | /* | 58 | /* |
59 | * instantiate a user defined key | 59 | * instantiate a user defined key |
60 | */ | 60 | */ |
61 | int user_instantiate(struct key *key, const void *data, size_t datalen) | 61 | int user_instantiate(struct key *key, struct key_preparsed_payload *prep) |
62 | { | 62 | { |
63 | struct user_key_payload *upayload; | 63 | struct user_key_payload *upayload; |
64 | size_t datalen = prep->datalen; | ||
64 | int ret; | 65 | int ret; |
65 | 66 | ||
66 | ret = -EINVAL; | 67 | ret = -EINVAL; |
67 | if (datalen <= 0 || datalen > 32767 || !data) | 68 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
68 | goto error; | 69 | goto error; |
69 | 70 | ||
70 | ret = key_payload_reserve(key, datalen); | 71 | ret = key_payload_reserve(key, datalen); |
@@ -78,7 +79,7 @@ int user_instantiate(struct key *key, const void *data, size_t datalen) | |||
78 | 79 | ||
79 | /* attach the data */ | 80 | /* attach the data */ |
80 | upayload->datalen = datalen; | 81 | upayload->datalen = datalen; |
81 | memcpy(upayload->data, data, datalen); | 82 | memcpy(upayload->data, prep->data, datalen); |
82 | rcu_assign_keypointer(key, upayload); | 83 | rcu_assign_keypointer(key, upayload); |
83 | ret = 0; | 84 | ret = 0; |
84 | 85 | ||
@@ -92,13 +93,14 @@ EXPORT_SYMBOL_GPL(user_instantiate); | |||
92 | * update a user defined key | 93 | * update a user defined key |
93 | * - the key's semaphore is write-locked | 94 | * - the key's semaphore is write-locked |
94 | */ | 95 | */ |
95 | int user_update(struct key *key, const void *data, size_t datalen) | 96 | int user_update(struct key *key, struct key_preparsed_payload *prep) |
96 | { | 97 | { |
97 | struct user_key_payload *upayload, *zap; | 98 | struct user_key_payload *upayload, *zap; |
99 | size_t datalen = prep->datalen; | ||
98 | int ret; | 100 | int ret; |
99 | 101 | ||
100 | ret = -EINVAL; | 102 | ret = -EINVAL; |
101 | if (datalen <= 0 || datalen > 32767 || !data) | 103 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
102 | goto error; | 104 | goto error; |
103 | 105 | ||
104 | /* construct a replacement payload */ | 106 | /* construct a replacement payload */ |
@@ -108,7 +110,7 @@ int user_update(struct key *key, const void *data, size_t datalen) | |||
108 | goto error; | 110 | goto error; |
109 | 111 | ||
110 | upayload->datalen = datalen; | 112 | upayload->datalen = datalen; |
111 | memcpy(upayload->data, data, datalen); | 113 | memcpy(upayload->data, prep->data, datalen); |
112 | 114 | ||
113 | /* check the quota and attach the new data */ | 115 | /* check the quota and attach the new data */ |
114 | zap = upayload; | 116 | zap = upayload; |