linux/kernel/module_signing.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* Module signature checker
   3 *
   4 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
   5 * Written by David Howells (dhowells@redhat.com)
   6 */
   7
   8#include <linux/kernel.h>
   9#include <linux/errno.h>
  10#include <linux/string.h>
  11#include <linux/verification.h>
  12#include <crypto/public_key.h>
  13#include "module-internal.h"
  14
  15enum pkey_id_type {
  16        PKEY_ID_PGP,            /* OpenPGP generated key ID */
  17        PKEY_ID_X509,           /* X.509 arbitrary subjectKeyIdentifier */
  18        PKEY_ID_PKCS7,          /* Signature in PKCS#7 message */
  19};
  20
  21/*
  22 * Module signature information block.
  23 *
  24 * The constituents of the signature section are, in order:
  25 *
  26 *      - Signer's name
  27 *      - Key identifier
  28 *      - Signature data
  29 *      - Information block
  30 */
  31struct module_signature {
  32        u8      algo;           /* Public-key crypto algorithm [0] */
  33        u8      hash;           /* Digest algorithm [0] */
  34        u8      id_type;        /* Key identifier type [PKEY_ID_PKCS7] */
  35        u8      signer_len;     /* Length of signer's name [0] */
  36        u8      key_id_len;     /* Length of key identifier [0] */
  37        u8      __pad[3];
  38        __be32  sig_len;        /* Length of signature data */
  39};
  40
  41/*
  42 * Verify the signature on a module.
  43 */
  44int mod_verify_sig(const void *mod, struct load_info *info)
  45{
  46        struct module_signature ms;
  47        size_t sig_len, modlen = info->len;
  48
  49        pr_devel("==>%s(,%zu)\n", __func__, modlen);
  50
  51        if (modlen <= sizeof(ms))
  52                return -EBADMSG;
  53
  54        memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
  55        modlen -= sizeof(ms);
  56
  57        sig_len = be32_to_cpu(ms.sig_len);
  58        if (sig_len >= modlen)
  59                return -EBADMSG;
  60        modlen -= sig_len;
  61        info->len = modlen;
  62
  63        if (ms.id_type != PKEY_ID_PKCS7) {
  64                pr_err("%s: Module is not signed with expected PKCS#7 message\n",
  65                       info->name);
  66                return -ENOPKG;
  67        }
  68
  69        if (ms.algo != 0 ||
  70            ms.hash != 0 ||
  71            ms.signer_len != 0 ||
  72            ms.key_id_len != 0 ||
  73            ms.__pad[0] != 0 ||
  74            ms.__pad[1] != 0 ||
  75            ms.__pad[2] != 0) {
  76                pr_err("%s: PKCS#7 signature info has unexpected non-zero params\n",
  77                       info->name);
  78                return -EBADMSG;
  79        }
  80
  81        return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
  82                                      VERIFY_USE_SECONDARY_KEYRING,
  83                                      VERIFYING_MODULE_SIGNATURE,
  84                                      NULL, NULL);
  85}
  86