On Tue, 2017-04-18 at 17:17 -0300, Thiago Jung Bauermann wrote:
> IMA will use the module_signature format for append signatures, so export
> the relevant definitions and factor out the code which verifies that the
> appended signature trailer is valid.
> 
> Also, create a CONFIG_MODULE_SIG_FORMAT option so that IMA can select it
> and be able to use validate_module_signature without having to depend on
> CONFIG_MODULE_SIG.

Basically we want to generalize the concept of an appended signature.
 Referring to it as a "module signature format" seems a bit confusing.

David, would you have a problem with changing the appended string from
"~Module signature appended~\n" to something more generic?  The
appended signature format could be used by anything calling
kernel_read_file() (eg. kexec kernel image/initramfs).

Mimi

> Signed-off-by: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>
> ---
>  include/linux/module_signature.h | 45 ++++++++++++++++++++++++
>  init/Kconfig                     |  6 +++-
>  kernel/Makefile                  |  2 +-
>  kernel/module_signing.c          | 74 
> +++++++++++++++++-----------------------
>  4 files changed, 82 insertions(+), 45 deletions(-)
> 
> diff --git a/include/linux/module_signature.h 
> b/include/linux/module_signature.h
> new file mode 100644
> index 000000000000..b04f16559b47
> --- /dev/null
> +++ b/include/linux/module_signature.h
> @@ -0,0 +1,45 @@
> +/* Module signature handling.
> + *
> + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
> + * Written by David Howells (dhowe...@redhat.com)
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public Licence
> + * as published by the Free Software Foundation; either version
> + * 2 of the Licence, or (at your option) any later version.
> + */
> +
> +#ifndef _LINUX_MODULE_SIGNATURE_H
> +#define _LINUX_MODULE_SIGNATURE_H
> +
> +enum pkey_id_type {
> +     PKEY_ID_PGP,            /* OpenPGP generated key ID */
> +     PKEY_ID_X509,           /* X.509 arbitrary subjectKeyIdentifier */
> +     PKEY_ID_PKCS7,          /* Signature in PKCS#7 message */
> +};
> +
> +/*
> + * Module signature information block.
> + *
> + * The constituents of the signature section are, in order:
> + *
> + *   - Signer's name
> + *   - Key identifier
> + *   - Signature data
> + *   - Information block
> + */
> +struct module_signature {
> +     u8      algo;           /* Public-key crypto algorithm [0] */
> +     u8      hash;           /* Digest algorithm [0] */
> +     u8      id_type;        /* Key identifier type [PKEY_ID_PKCS7] */
> +     u8      signer_len;     /* Length of signer's name [0] */
> +     u8      key_id_len;     /* Length of key identifier [0] */
> +     u8      __pad[3];
> +     __be32  sig_len;        /* Length of signature data */
> +};
> +
> +int validate_module_signature(const struct module_signature *ms,
> +                           size_t file_len);
> +int mod_verify_sig(const void *mod, unsigned long *_modlen);
> +
> +#endif /* _LINUX_MODULE_SIGNATURE_H */
> diff --git a/init/Kconfig b/init/Kconfig
> index a92f27da4a27..891325e5aeff 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -2024,7 +2024,7 @@ config MODULE_SRCVERSION_ALL
>  config MODULE_SIG
>       bool "Module signature verification"
>       depends on MODULES
> -     select SYSTEM_DATA_VERIFICATION
> +     select MODULE_SIG_FORMAT
>       help
>         Check modules for valid signatures upon load: the signature
>         is simply appended to the module. For more information see
> @@ -2039,6 +2039,10 @@ config MODULE_SIG
>         debuginfo strip done by some packagers (such as rpmbuild) and
>         inclusion into an initramfs that wants the module size reduced.
> 
> +config MODULE_SIG_FORMAT
> +     def_bool n
> +     select SYSTEM_DATA_VERIFICATION
> +
>  config MODULE_SIG_FORCE
>       bool "Require modules to be validly signed"
>       depends on MODULE_SIG
> diff --git a/kernel/Makefile b/kernel/Makefile
> index b302b4731d16..4451bbc70a08 100644
> --- a/kernel/Makefile
> +++ b/kernel/Makefile
> @@ -56,7 +56,7 @@ obj-y += up.o
>  endif
>  obj-$(CONFIG_UID16) += uid16.o
>  obj-$(CONFIG_MODULES) += module.o
> -obj-$(CONFIG_MODULE_SIG) += module_signing.o
> +obj-$(CONFIG_MODULE_SIG_FORMAT) += module_signing.o
>  obj-$(CONFIG_KALLSYMS) += kallsyms.o
>  obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
>  obj-$(CONFIG_KEXEC_CORE) += kexec_core.o
> diff --git a/kernel/module_signing.c b/kernel/module_signing.c
> index 937c844bee4a..421e3e668714 100644
> --- a/kernel/module_signing.c
> +++ b/kernel/module_signing.c
> @@ -11,36 +11,38 @@
> 
>  #include <linux/kernel.h>
>  #include <linux/errno.h>
> +#include <linux/module_signature.h>
>  #include <linux/string.h>
>  #include <linux/verification.h>
>  #include <crypto/public_key.h>
>  #include "module-internal.h"
> 
> -enum pkey_id_type {
> -     PKEY_ID_PGP,            /* OpenPGP generated key ID */
> -     PKEY_ID_X509,           /* X.509 arbitrary subjectKeyIdentifier */
> -     PKEY_ID_PKCS7,          /* Signature in PKCS#7 message */
> -};
> -
> -/*
> - * Module signature information block.
> - *
> - * The constituents of the signature section are, in order:
> +/**
> + * validate_module_signature - validate that the given signature is sane
>   *
> - *   - Signer's name
> - *   - Key identifier
> - *   - Signature data
> - *   - Information block
> + * @ms:              Signature to validate.
> + * @file_len:        Size of the file to which @ms is appended.
>   */
> -struct module_signature {
> -     u8      algo;           /* Public-key crypto algorithm [0] */
> -     u8      hash;           /* Digest algorithm [0] */
> -     u8      id_type;        /* Key identifier type [PKEY_ID_PKCS7] */
> -     u8      signer_len;     /* Length of signer's name [0] */
> -     u8      key_id_len;     /* Length of key identifier [0] */
> -     u8      __pad[3];
> -     __be32  sig_len;        /* Length of signature data */
> -};
> +int validate_module_signature(const struct module_signature *ms, size_t 
> file_len)
> +{
> +     if (be32_to_cpu(ms->sig_len) >= file_len - sizeof(*ms))
> +             return -EBADMSG;
> +     else if (ms->id_type != PKEY_ID_PKCS7) {
> +             pr_err("Module is not signed with expected PKCS#7 message\n");
> +             return -ENOPKG;
> +     } else if (ms->algo != 0 ||
> +                ms->hash != 0 ||
> +                ms->signer_len != 0 ||
> +                ms->key_id_len != 0 ||
> +                ms->__pad[0] != 0 ||
> +                ms->__pad[1] != 0 ||
> +                ms->__pad[2] != 0) {
> +             pr_err("PKCS#7 signature info has unexpected non-zero 
> params\n");
> +             return -EBADMSG;
> +     }
> +
> +     return 0;
> +}
> 
>  /*
>   * Verify the signature on a module.
> @@ -49,6 +51,7 @@ int mod_verify_sig(const void *mod, unsigned long *_modlen)
>  {
>       struct module_signature ms;
>       size_t modlen = *_modlen, sig_len;
> +     int ret;
> 
>       pr_devel("==>%s(,%zu)\n", __func__, modlen);
> 
> @@ -56,30 +59,15 @@ int mod_verify_sig(const void *mod, unsigned long 
> *_modlen)
>               return -EBADMSG;
> 
>       memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
> -     modlen -= sizeof(ms);
> +
> +     ret = validate_module_signature(&ms, modlen);
> +     if (ret)
> +             return ret;
> 
>       sig_len = be32_to_cpu(ms.sig_len);
> -     if (sig_len >= modlen)
> -             return -EBADMSG;
> -     modlen -= sig_len;
> +     modlen -= sig_len + sizeof(ms);
>       *_modlen = modlen;
> 
> -     if (ms.id_type != PKEY_ID_PKCS7) {
> -             pr_err("Module is not signed with expected PKCS#7 message\n");
> -             return -ENOPKG;
> -     }
> -
> -     if (ms.algo != 0 ||
> -         ms.hash != 0 ||
> -         ms.signer_len != 0 ||
> -         ms.key_id_len != 0 ||
> -         ms.__pad[0] != 0 ||
> -         ms.__pad[1] != 0 ||
> -         ms.__pad[2] != 0) {
> -             pr_err("PKCS#7 signature info has unexpected non-zero 
> params\n");
> -             return -EBADMSG;
> -     }
> -
>       return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
>                                     NULL, VERIFYING_MODULE_SIGNATURE,
>                                     NULL, NULL);

Reply via email to