diff options
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; |
