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