Back to home page

LXR

 
 

    


0001 /* Module signature checker
0002  *
0003  * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
0004  * Written by David Howells (dhowells@redhat.com)
0005  *
0006  * This program is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU General Public Licence
0008  * as published by the Free Software Foundation; either version
0009  * 2 of the Licence, or (at your option) any later version.
0010  */
0011 
0012 #include <linux/kernel.h>
0013 #include <linux/errno.h>
0014 #include <linux/string.h>
0015 #include <linux/verification.h>
0016 #include <crypto/public_key.h>
0017 #include "module-internal.h"
0018 
0019 enum pkey_id_type {
0020     PKEY_ID_PGP,        /* OpenPGP generated key ID */
0021     PKEY_ID_X509,       /* X.509 arbitrary subjectKeyIdentifier */
0022     PKEY_ID_PKCS7,      /* Signature in PKCS#7 message */
0023 };
0024 
0025 /*
0026  * Module signature information block.
0027  *
0028  * The constituents of the signature section are, in order:
0029  *
0030  *  - Signer's name
0031  *  - Key identifier
0032  *  - Signature data
0033  *  - Information block
0034  */
0035 struct module_signature {
0036     u8  algo;       /* Public-key crypto algorithm [0] */
0037     u8  hash;       /* Digest algorithm [0] */
0038     u8  id_type;    /* Key identifier type [PKEY_ID_PKCS7] */
0039     u8  signer_len; /* Length of signer's name [0] */
0040     u8  key_id_len; /* Length of key identifier [0] */
0041     u8  __pad[3];
0042     __be32  sig_len;    /* Length of signature data */
0043 };
0044 
0045 /*
0046  * Verify the signature on a module.
0047  */
0048 int mod_verify_sig(const void *mod, unsigned long *_modlen)
0049 {
0050     struct module_signature ms;
0051     size_t modlen = *_modlen, sig_len;
0052 
0053     pr_devel("==>%s(,%zu)\n", __func__, modlen);
0054 
0055     if (modlen <= sizeof(ms))
0056         return -EBADMSG;
0057 
0058     memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
0059     modlen -= sizeof(ms);
0060 
0061     sig_len = be32_to_cpu(ms.sig_len);
0062     if (sig_len >= modlen)
0063         return -EBADMSG;
0064     modlen -= sig_len;
0065     *_modlen = modlen;
0066 
0067     if (ms.id_type != PKEY_ID_PKCS7) {
0068         pr_err("Module is not signed with expected PKCS#7 message\n");
0069         return -ENOPKG;
0070     }
0071 
0072     if (ms.algo != 0 ||
0073         ms.hash != 0 ||
0074         ms.signer_len != 0 ||
0075         ms.key_id_len != 0 ||
0076         ms.__pad[0] != 0 ||
0077         ms.__pad[1] != 0 ||
0078         ms.__pad[2] != 0) {
0079         pr_err("PKCS#7 signature info has unexpected non-zero params\n");
0080         return -EBADMSG;
0081     }
0082 
0083     return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
0084                       NULL, VERIFYING_MODULE_SIGNATURE,
0085                       NULL, NULL);
0086 }