blob: 6528a79d998d08120e9e80524164e5c759d911f3 [file] [log] [blame]
Rusty Russell106a4ee2012-09-26 10:09:40 +01001/* 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>
David Howells146aa8b2015-10-21 14:04:48 +010013#include <linux/errno.h>
David Howellsb56e5a12013-08-30 16:07:30 +010014#include <keys/system_keyring.h>
David Howells3f1e1be2015-07-20 21:16:27 +010015#include <crypto/public_key.h>
Rusty Russell106a4ee2012-09-26 10:09:40 +010016#include "module-internal.h"
17
18/*
David Howells48ba2462012-09-26 10:11:03 +010019 * Module signature information block.
20 *
21 * The constituents of the signature section are, in order:
22 *
23 * - Signer's name
24 * - Key identifier
25 * - Signature data
26 * - Information block
27 */
28struct module_signature {
David Howells3f1e1be2015-07-20 21:16:27 +010029 u8 algo; /* Public-key crypto algorithm [0] */
30 u8 hash; /* Digest algorithm [0] */
31 u8 id_type; /* Key identifier type [PKEY_ID_PKCS7] */
32 u8 signer_len; /* Length of signer's name [0] */
33 u8 key_id_len; /* Length of key identifier [0] */
David Howells12e130b2012-10-22 15:05:48 +010034 u8 __pad[3];
35 __be32 sig_len; /* Length of signature data */
David Howells48ba2462012-09-26 10:11:03 +010036};
37
38/*
Rusty Russell106a4ee2012-09-26 10:09:40 +010039 * Verify the signature on a module.
40 */
David Howellscaabe242012-10-20 01:19:29 +010041int mod_verify_sig(const void *mod, unsigned long *_modlen)
Rusty Russell106a4ee2012-09-26 10:09:40 +010042{
David Howells48ba2462012-09-26 10:11:03 +010043 struct module_signature ms;
David Howellscaabe242012-10-20 01:19:29 +010044 size_t modlen = *_modlen, sig_len;
David Howells48ba2462012-09-26 10:11:03 +010045
Randy Dunlap0390c882012-10-20 18:59:31 -070046 pr_devel("==>%s(,%zu)\n", __func__, modlen);
David Howells48ba2462012-09-26 10:11:03 +010047
David Howellscaabe242012-10-20 01:19:29 +010048 if (modlen <= sizeof(ms))
David Howells48ba2462012-09-26 10:11:03 +010049 return -EBADMSG;
50
David Howellscaabe242012-10-20 01:19:29 +010051 memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
52 modlen -= sizeof(ms);
David Howells48ba2462012-09-26 10:11:03 +010053
54 sig_len = be32_to_cpu(ms.sig_len);
David Howellscaabe242012-10-20 01:19:29 +010055 if (sig_len >= modlen)
David Howells48ba2462012-09-26 10:11:03 +010056 return -EBADMSG;
David Howellscaabe242012-10-20 01:19:29 +010057 modlen -= sig_len;
David Howellscaabe242012-10-20 01:19:29 +010058 *_modlen = modlen;
David Howells48ba2462012-09-26 10:11:03 +010059
David Howells3f1e1be2015-07-20 21:16:27 +010060 if (ms.id_type != PKEY_ID_PKCS7) {
61 pr_err("Module is not signed with expected PKCS#7 message\n");
David Howells48ba2462012-09-26 10:11:03 +010062 return -ENOPKG;
David Howells48ba2462012-09-26 10:11:03 +010063 }
64
David Howells3f1e1be2015-07-20 21:16:27 +010065 if (ms.algo != 0 ||
66 ms.hash != 0 ||
67 ms.signer_len != 0 ||
68 ms.key_id_len != 0 ||
69 ms.__pad[0] != 0 ||
70 ms.__pad[1] != 0 ||
71 ms.__pad[2] != 0) {
72 pr_err("PKCS#7 signature info has unexpected non-zero params\n");
73 return -EBADMSG;
74 }
David Howells48ba2462012-09-26 10:11:03 +010075
David Howells99db4432015-08-05 15:22:27 +010076 return system_verify_data(mod, modlen, mod + modlen, sig_len,
77 VERIFYING_MODULE_SIGNATURE);
Rusty Russell106a4ee2012-09-26 10:09:40 +010078}