fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / kernel / module-verify-sig.c
1 /* module-verify-sig.c: module signature checker
2  *
3  * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  * - Derived from GregKH's RSA module signer
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version
10  * 2 of the License, or (at your option) any later version.
11  */
12
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/slab.h>
16 #include <linux/elf.h>
17 #include <linux/crypto.h>
18 #include <linux/crypto/ksign.h>
19 #include "module-verify.h"
20
21 #undef MODSIGN_DEBUG
22
23 #ifdef MODSIGN_DEBUG
24 #define _debug(FMT, ...) printk(FMT, ##__VA_ARGS__)
25 #else
26 #define _debug(FMT, ...) do {} while (0)
27 #endif
28
29 #ifdef MODSIGN_DEBUG
30 #define count_and_csum(C, __p,__n)                      \
31 do {                                                    \
32         int __loop;                                     \
33         for (__loop = 0; __loop < __n; __loop++) {      \
34                 (C)->csum += __p[__loop];               \
35                 (C)->xcsum += __p[__loop];              \
36         }                                               \
37         (C)->signed_size += __n;                        \
38 } while(0)
39 #else
40 #define count_and_csum(C, __p,__n)              \
41 do {                                            \
42         (C)->signed_size += __n;                \
43 } while(0)
44 #endif
45
46 #define crypto_digest_update_data(C,PTR,N)                      \
47 do {                                                            \
48         size_t __n = (N);                                       \
49         uint8_t *__p = (uint8_t *)(PTR);                        \
50         count_and_csum((C), __p, __n);                          \
51         crypto_hash_update_kernel(&(C)->hash, __p, __n);        \
52 } while(0)
53
54 #define crypto_digest_update_val(C,VAL)                         \
55 do {                                                            \
56         size_t __n = sizeof(VAL);                               \
57         uint8_t *__p = (uint8_t *)&(VAL);                       \
58         count_and_csum((C), __p, __n);                          \
59         crypto_hash_update_kernel(&(C)->hash, __p, __n);        \
60 } while(0)
61
62 static int module_verify_canonicalise(struct module_verify_data *mvdata);
63
64 static int extract_elf_rela(struct module_verify_data *mvdata,
65                             int secix,
66                             const Elf_Rela *relatab, size_t nrels,
67                             const char *sh_name);
68
69 static int extract_elf_rel(struct module_verify_data *mvdata,
70                            int secix,
71                            const Elf_Rel *reltab, size_t nrels,
72                            const char *sh_name);
73
74 static int signedonly;
75
76 static int __init sign_setup(char *str)
77 {
78         signedonly = 1;
79         return 0;
80 }
81 __setup("enforcemodulesig", sign_setup);
82
83 /*
84  * verify a module's signature
85  */
86 int module_verify_signature(struct module_verify_data *mvdata)
87 {
88         const Elf_Shdr *sechdrs = mvdata->sections;
89         const char *secstrings = mvdata->secstrings;
90         const char *sig;
91         unsigned sig_size;
92         int i, ret;
93
94         for (i = 1; i < mvdata->nsects; i++) {
95                 switch (sechdrs[i].sh_type) {
96                 case SHT_PROGBITS:
97                         if (strcmp(mvdata->secstrings + sechdrs[i].sh_name,
98                                    ".module_sig") == 0) {
99                                 mvdata->sig_index = i;
100                         }
101                         break;
102                 }
103         }
104
105         if (mvdata->sig_index <= 0)
106                 goto no_signature;
107
108         sig = mvdata->buffer + sechdrs[mvdata->sig_index].sh_offset;
109         sig_size = sechdrs[mvdata->sig_index].sh_size;
110
111         _debug("sig in section %d (size %d)\n",
112                mvdata->sig_index, sig_size);
113
114         /* produce a canonicalisation map for the sections */
115         ret = module_verify_canonicalise(mvdata);
116         if (ret < 0)
117                 return ret;
118
119         /* grab an SHA1 transformation context
120          * - !!! if this tries to load the sha1.ko module, we will deadlock!!!
121          */
122         mvdata->hash.tfm = crypto_hash_cast(crypto_alloc_tfm2("sha1", 0, 1));
123         if (!mvdata->hash.tfm) {
124                 printk("Couldn't load module - SHA1 transform unavailable\n");
125                 return -EPERM;
126         }
127
128         crypto_hash_init(&mvdata->hash);
129
130 #ifdef MODSIGN_DEBUG
131         mvdata->xcsum = 0;
132 #endif
133
134         /* load data from each relevant section into the digest */
135         for (i = 1; i < mvdata->nsects; i++) {
136                 unsigned long sh_type = sechdrs[i].sh_type;
137                 unsigned long sh_info = sechdrs[i].sh_info;
138                 unsigned long sh_size = sechdrs[i].sh_size;
139                 unsigned long sh_flags = sechdrs[i].sh_flags;
140                 const char *sh_name = secstrings + sechdrs[i].sh_name;
141                 const void *data = mvdata->buffer + sechdrs[i].sh_offset;
142
143                 if (i == mvdata->sig_index)
144                         continue;
145
146 #ifdef MODSIGN_DEBUG
147                 mvdata->csum = 0;
148 #endif
149
150                 /* it would be nice to include relocation sections, but the act
151                  * of adding a signature to the module seems changes their
152                  * contents, because the symtab gets changed when sections are
153                  * added or removed */
154                 if (sh_type == SHT_REL || sh_type == SHT_RELA) {
155                         if (mvdata->canonlist[sh_info]) {
156                                 uint32_t xsh_info = mvdata->canonmap[sh_info];
157
158                                 crypto_digest_update_data(mvdata, sh_name, strlen(sh_name));
159                                 crypto_digest_update_val(mvdata, sechdrs[i].sh_type);
160                                 crypto_digest_update_val(mvdata, sechdrs[i].sh_flags);
161                                 crypto_digest_update_val(mvdata, sechdrs[i].sh_size);
162                                 crypto_digest_update_val(mvdata, sechdrs[i].sh_addralign);
163                                 crypto_digest_update_val(mvdata, xsh_info);
164
165                                 if (sh_type == SHT_RELA)
166                                         ret = extract_elf_rela(
167                                                 mvdata, i,
168                                                 data,
169                                                 sh_size / sizeof(Elf_Rela),
170                                                 sh_name);
171                                 else
172                                         ret = extract_elf_rel(
173                                                 mvdata, i,
174                                                 data,
175                                                 sh_size / sizeof(Elf_Rel),
176                                                 sh_name);
177
178                                 if (ret < 0)
179                                         goto format_error;
180                         }
181
182                         continue;
183                 }
184
185                 /* include allocatable loadable sections */
186                 if (sh_type != SHT_NOBITS && sh_flags & SHF_ALLOC)
187                         goto include_section;
188
189                 continue;
190
191         include_section:
192                 crypto_digest_update_data(mvdata, sh_name, strlen(sh_name));
193                 crypto_digest_update_val(mvdata, sechdrs[i].sh_type);
194                 crypto_digest_update_val(mvdata, sechdrs[i].sh_flags);
195                 crypto_digest_update_val(mvdata, sechdrs[i].sh_size);
196                 crypto_digest_update_val(mvdata, sechdrs[i].sh_addralign);
197                 crypto_digest_update_data(mvdata, data, sh_size);
198
199                 _debug("%08zx %02x digested the %s section, size %ld\n",
200                        mvdata->signed_size, mvdata->csum, sh_name, sh_size);
201
202                 mvdata->canonlist[i] = 1;
203         }
204
205         _debug("Contributed %zu bytes to the digest (csum 0x%02x)\n",
206                mvdata->signed_size, mvdata->xcsum);
207
208         /* do the actual signature verification */
209         ret = ksign_verify_signature(sig, sig_size, mvdata->hash.tfm);
210
211         _debug("verify-sig : %d\n", ret);
212
213         switch (ret) {
214         case 0:                 /* good signature */
215                 ret = 1;
216                 break;
217         case -EKEYREJECTED:     /* signature mismatch or number format error */
218                 printk(KERN_ERR "Module signature verification failed\n");
219                 break;
220         case -ENOKEY:           /* signed, but we don't have the public key */
221                 printk(KERN_ERR "Module signed with unknown public key\n");
222                 break;
223         default:                /* other error (probably ENOMEM) */
224                 break;
225         }
226
227         return ret;
228
229 format_error:
230         crypto_free_hash(mvdata->hash.tfm);
231         printk(KERN_ERR "Module format error encountered\n");
232         return -ELIBBAD;
233
234         /* deal with the case of an unsigned module */
235 no_signature:
236         if (!signedonly)
237                 return 0;
238         printk(KERN_ERR "An attempt to load unsigned module was rejected\n");
239         return -EKEYREJECTED;
240 }
241
242 /*
243  * canonicalise the section table index numbers
244  */
245 static int module_verify_canonicalise(struct module_verify_data *mvdata)
246 {
247         int canon, loop, changed, tmp;
248
249         /* produce a list of index numbers of sections that contribute
250          * to the kernel's module image
251          */
252         mvdata->canonlist =
253                 kmalloc(sizeof(int) * mvdata->nsects * 2, GFP_KERNEL);
254         if (!mvdata->canonlist)
255                 return -ENOMEM;
256
257         mvdata->canonmap = mvdata->canonlist + mvdata->nsects;
258         canon = 0;
259
260         for (loop = 1; loop < mvdata->nsects; loop++) {
261                 const Elf_Shdr *section = mvdata->sections + loop;
262
263                 if (loop != mvdata->sig_index) {
264                         /* we only need to canonicalise allocatable sections */
265                         if (section->sh_flags & SHF_ALLOC)
266                                 mvdata->canonlist[canon++] = loop;
267                 }
268         }
269
270         /* canonicalise the index numbers of the contributing section */
271         do {
272                 changed = 0;
273
274                 for (loop = 0; loop < canon - 1; loop++) {
275                         const char *x, *y;
276
277                         x = mvdata->secstrings +
278                                 mvdata->sections[mvdata->canonlist[loop + 0]].sh_name;
279                         y = mvdata->secstrings +
280                                 mvdata->sections[mvdata->canonlist[loop + 1]].sh_name;
281
282                         if (strcmp(x, y) > 0) {
283                                 tmp = mvdata->canonlist[loop + 0];
284                                 mvdata->canonlist[loop + 0] =
285                                         mvdata->canonlist[loop + 1];
286                                 mvdata->canonlist[loop + 1] = tmp;
287                                 changed = 1;
288                         }
289                 }
290
291         } while(changed);
292
293         for (loop = 0; loop < canon; loop++)
294                 mvdata->canonmap[mvdata->canonlist[loop]] = loop + 1;
295
296         return 0;
297 }
298
299 /*
300  * extract an ELF RELA table
301  * - need to canonicalise the entries in case section addition/removal has
302  *   rearranged the symbol table and the section table
303  */
304 static int extract_elf_rela(struct module_verify_data *mvdata,
305                             int secix,
306                             const Elf_Rela *relatab, size_t nrels,
307                             const char *sh_name)
308 {
309         struct {
310 #if defined(MODULES_ARE_ELF32)
311                 uint32_t        r_offset;
312                 uint32_t        r_addend;
313                 uint32_t        st_value;
314                 uint32_t        st_size;
315                 uint16_t        st_shndx;
316                 uint8_t         r_type;
317                 uint8_t         st_info;
318                 uint8_t         st_other;
319 #elif defined(MODULES_ARE_ELF64)
320                 uint64_t        r_offset;
321                 uint64_t        r_addend;
322                 uint64_t        st_value;
323                 uint64_t        st_size;
324                 uint32_t        r_type;
325                 uint16_t        st_shndx;
326                 uint8_t         st_info;
327                 uint8_t         st_other;
328 #else
329 #error unsupported module type
330 #endif
331         } __attribute__((packed)) relocation;
332
333         const Elf_Rela *reloc;
334         const Elf_Sym *symbol;
335         size_t loop;
336
337         /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
338         for (loop = 0; loop < nrels; loop++) {
339                 int st_shndx;
340
341                 reloc = &relatab[loop];
342
343                 /* decode the relocation */
344                 relocation.r_offset = reloc->r_offset;
345                 relocation.r_addend = reloc->r_addend;
346                 relocation.r_type = ELF_R_TYPE(reloc->r_info);
347
348                 /* decode the symbol referenced by the relocation */
349                 symbol = &mvdata->symbols[ELF_R_SYM(reloc->r_info)];
350                 relocation.st_info = symbol->st_info;
351                 relocation.st_other = symbol->st_other;
352                 relocation.st_value = symbol->st_value;
353                 relocation.st_size = symbol->st_size;
354                 relocation.st_shndx = symbol->st_shndx;
355                 st_shndx = symbol->st_shndx;
356
357                 /* canonicalise the section used by the symbol */
358                 if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects)
359                         relocation.st_shndx = mvdata->canonmap[st_shndx];
360
361                 crypto_digest_update_val(mvdata, relocation);
362
363                 /* undefined symbols must be named if referenced */
364                 if (st_shndx == SHN_UNDEF) {
365                         const char *name = mvdata->strings + symbol->st_name;
366                         crypto_digest_update_data(mvdata,
367                                                   name, strlen(name) + 1);
368                 }
369         }
370
371         _debug("%08zx %02x digested the %s section, nrels %zu\n",
372                mvdata->signed_size, mvdata->csum, sh_name, nrels);
373
374         return 0;
375 }
376
377 /*
378  * extract an ELF REL table
379  * - need to canonicalise the entries in case section addition/removal has
380  *   rearranged the symbol table and the section table
381  */
382 static int extract_elf_rel(struct module_verify_data *mvdata,
383                            int secix,
384                            const Elf_Rel *reltab, size_t nrels,
385                            const char *sh_name)
386 {
387         struct {
388 #if defined(MODULES_ARE_ELF32)
389                 uint32_t        r_offset;
390                 uint32_t        st_value;
391                 uint32_t        st_size;
392                 uint16_t        st_shndx;
393                 uint8_t         r_type;
394                 uint8_t         st_info;
395                 uint8_t         st_other;
396 #elif defined(MODULES_ARE_ELF64)
397                 uint64_t        r_offset;
398                 uint64_t        st_value;
399                 uint64_t        st_size;
400                 uint32_t        r_type;
401                 uint16_t        st_shndx;
402                 uint8_t         st_info;
403                 uint8_t         st_other;
404 #else
405 #error unsupported module type
406 #endif
407         } __attribute__((packed)) relocation;
408
409         const Elf_Rel *reloc;
410         const Elf_Sym *symbol;
411         size_t loop;
412
413         /* contribute the relevant bits from a join of { RELA, SYMBOL, SECTION } */
414         for (loop = 0; loop < nrels; loop++) {
415                 int st_shndx;
416
417                 reloc = &reltab[loop];
418
419                 /* decode the relocation */
420                 relocation.r_offset = reloc->r_offset;
421                 relocation.r_type = ELF_R_TYPE(reloc->r_info);
422
423                 /* decode the symbol referenced by the relocation */
424                 symbol = &mvdata->symbols[ELF_R_SYM(reloc->r_info)];
425                 relocation.st_info = symbol->st_info;
426                 relocation.st_other = symbol->st_other;
427                 relocation.st_value = symbol->st_value;
428                 relocation.st_size = symbol->st_size;
429                 relocation.st_shndx = symbol->st_shndx;
430                 st_shndx = symbol->st_shndx;
431
432                 /* canonicalise the section used by the symbol */
433                 if (st_shndx > SHN_UNDEF && st_shndx < mvdata->nsects)
434                         relocation.st_shndx = mvdata->canonmap[st_shndx];
435
436                 crypto_digest_update_val(mvdata, relocation);
437
438                 /* undefined symbols must be named if referenced */
439                 if (st_shndx == SHN_UNDEF) {
440                         const char *name = mvdata->strings + symbol->st_name;
441                         crypto_digest_update_data(mvdata,
442                                                   name, strlen(name) + 1);
443                 }
444         }
445
446         _debug("%08zx %02x digested the %s section, nrels %zu\n",
447                mvdata->signed_size, mvdata->csum, sh_name, nrels);
448
449         return 0;
450 }