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/err.h>
  14#include <crypto/public_key.h>
  15#include <crypto/hash.h>
  16#include <keys/asymmetric-type.h>
  17#include <keys/system_keyring.h>
  18#include "module-internal.h"
  19
  20/*
  21 * Module signature information block.
  22 *
  23 * The constituents of the signature section are, in order:
  24 *
  25 *      - Signer's name
  26 *      - Key identifier
  27 *      - Signature data
  28 *      - Information block
  29 */
  30struct module_signature {
  31        u8      algo;           /* Public-key crypto algorithm [enum pkey_algo] */
  32        u8      hash;           /* Digest algorithm [enum hash_algo] */
  33        u8      id_type;        /* Key identifier type [enum pkey_id_type] */
  34        u8      signer_len;     /* Length of signer's name */
  35        u8      key_id_len;     /* Length of key identifier */
  36        u8      __pad[3];
  37        __be32  sig_len;        /* Length of signature data */
  38};
  39
  40/*
  41 * Digest the module contents.
  42 */
  43static struct public_key_signature *mod_make_digest(enum hash_algo hash,
  44                                                    const void *mod,
  45                                                    unsigned long modlen)
  46{
  47        struct public_key_signature *pks;
  48        struct crypto_shash *tfm;
  49        struct shash_desc *desc;
  50        size_t digest_size, desc_size;
  51        int ret;
  52
  53        pr_devel("==>%s()\n", __func__);
  54        
  55        /* Allocate the hashing algorithm we're going to need and find out how
  56         * big the hash operational data will be.
  57         */
  58        tfm = crypto_alloc_shash(hash_algo_name[hash], 0, 0);
  59        if (IS_ERR(tfm))
  60                return (PTR_ERR(tfm) == -ENOENT) ? ERR_PTR(-ENOPKG) : ERR_CAST(tfm);
  61
  62        desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
  63        digest_size = crypto_shash_digestsize(tfm);
  64
  65        /* We allocate the hash operational data storage on the end of our
  66         * context data and the digest output buffer on the end of that.
  67         */
  68        ret = -ENOMEM;
  69        pks = kzalloc(digest_size + sizeof(*pks) + desc_size, GFP_KERNEL);
  70        if (!pks)
  71                goto error_no_pks;
  72
  73        pks->pkey_hash_algo     = hash;
  74        pks->digest             = (u8 *)pks + sizeof(*pks) + desc_size;
  75        pks->digest_size        = digest_size;
  76
  77        desc = (void *)pks + sizeof(*pks);
  78        desc->tfm   = tfm;
  79        desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
  80
  81        ret = crypto_shash_init(desc);
  82        if (ret < 0)
  83                goto error;
  84
  85        ret = crypto_shash_finup(desc, mod, modlen, pks->digest);
  86        if (ret < 0)
  87                goto error;
  88
  89        crypto_free_shash(tfm);
  90        pr_devel("<==%s() = ok\n", __func__);
  91        return pks;
  92
  93error:
  94        kfree(pks);
  95error_no_pks:
  96        crypto_free_shash(tfm);
  97        pr_devel("<==%s() = %d\n", __func__, ret);
  98        return ERR_PTR(ret);
  99}
 100
 101/*
 102 * Extract an MPI array from the signature data.  This represents the actual
 103 * signature.  Each raw MPI is prefaced by a BE 2-byte value indicating the
 104 * size of the MPI in bytes.
 105 *
 106 * RSA signatures only have one MPI, so currently we only read one.
 107 */
 108static int mod_extract_mpi_array(struct public_key_signature *pks,
 109                                 const void *data, size_t len)
 110{
 111        size_t nbytes;
 112        MPI mpi;
 113
 114        if (len < 3)
 115                return -EBADMSG;
 116        nbytes = ((const u8 *)data)[0] << 8 | ((const u8 *)data)[1];
 117        data += 2;
 118        len -= 2;
 119        if (len != nbytes)
 120                return -EBADMSG;
 121
 122        mpi = mpi_read_raw_data(data, nbytes);
 123        if (!mpi)
 124                return -ENOMEM;
 125        pks->mpi[0] = mpi;
 126        pks->nr_mpi = 1;
 127        return 0;
 128}
 129
 130/*
 131 * Request an asymmetric key.
 132 */
 133static struct key *request_asymmetric_key(const char *signer, size_t signer_len,
 134                                          const u8 *key_id, size_t key_id_len)
 135{
 136        key_ref_t key;
 137        size_t i;
 138        char *id, *q;
 139
 140        pr_devel("==>%s(,%zu,,%zu)\n", __func__, signer_len, key_id_len);
 141
 142        /* Construct an identifier. */
 143        id = kmalloc(signer_len + 2 + key_id_len * 2 + 1, GFP_KERNEL);
 144        if (!id)
 145                return ERR_PTR(-ENOKEY);
 146
 147        memcpy(id, signer, signer_len);
 148
 149        q = id + signer_len;
 150        *q++ = ':';
 151        *q++ = ' ';
 152        for (i = 0; i < key_id_len; i++) {
 153                *q++ = hex_asc[*key_id >> 4];
 154                *q++ = hex_asc[*key_id++ & 0x0f];
 155        }
 156
 157        *q = 0;
 158
 159        pr_debug("Look up: \"%s\"\n", id);
 160
 161        key = keyring_search(make_key_ref(system_trusted_keyring, 1),
 162                             &key_type_asymmetric, id);
 163        if (IS_ERR(key))
 164                pr_warn("Request for unknown module key '%s' err %ld\n",
 165                        id, PTR_ERR(key));
 166        kfree(id);
 167
 168        if (IS_ERR(key)) {
 169                switch (PTR_ERR(key)) {
 170                        /* Hide some search errors */
 171                case -EACCES:
 172                case -ENOTDIR:
 173                case -EAGAIN:
 174                        return ERR_PTR(-ENOKEY);
 175                default:
 176                        return ERR_CAST(key);
 177                }
 178        }
 179
 180        pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key)));
 181        return key_ref_to_ptr(key);
 182}
 183
 184/*
 185 * Verify the signature on a module.
 186 */
 187int mod_verify_sig(const void *mod, unsigned long *_modlen)
 188{
 189        struct public_key_signature *pks;
 190        struct module_signature ms;
 191        struct key *key;
 192        const void *sig;
 193        size_t modlen = *_modlen, sig_len;
 194        int ret;
 195
 196        pr_devel("==>%s(,%zu)\n", __func__, modlen);
 197
 198        if (modlen <= sizeof(ms))
 199                return -EBADMSG;
 200
 201        memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
 202        modlen -= sizeof(ms);
 203
 204        sig_len = be32_to_cpu(ms.sig_len);
 205        if (sig_len >= modlen)
 206                return -EBADMSG;
 207        modlen -= sig_len;
 208        if ((size_t)ms.signer_len + ms.key_id_len >= modlen)
 209                return -EBADMSG;
 210        modlen -= (size_t)ms.signer_len + ms.key_id_len;
 211
 212        *_modlen = modlen;
 213        sig = mod + modlen;
 214
 215        /* For the moment, only support RSA and X.509 identifiers */
 216        if (ms.algo != PKEY_ALGO_RSA ||
 217            ms.id_type != PKEY_ID_X509)
 218                return -ENOPKG;
 219
 220        if (ms.hash >= PKEY_HASH__LAST ||
 221            !hash_algo_name[ms.hash])
 222                return -ENOPKG;
 223
 224        key = request_asymmetric_key(sig, ms.signer_len,
 225                                     sig + ms.signer_len, ms.key_id_len);
 226        if (IS_ERR(key))
 227                return PTR_ERR(key);
 228
 229        pks = mod_make_digest(ms.hash, mod, modlen);
 230        if (IS_ERR(pks)) {
 231                ret = PTR_ERR(pks);
 232                goto error_put_key;
 233        }
 234
 235        ret = mod_extract_mpi_array(pks, sig + ms.signer_len + ms.key_id_len,
 236                                    sig_len);
 237        if (ret < 0)
 238                goto error_free_pks;
 239
 240        ret = verify_signature(key, pks);
 241        pr_devel("verify_signature() = %d\n", ret);
 242
 243error_free_pks:
 244        mpi_free(pks->rsa.s);
 245        kfree(pks);
 246error_put_key:
 247        key_put(key);
 248        pr_devel("<==%s() = %d\n", __func__, ret);
 249        return ret;     
 250}
 251