linux/certs/blacklist.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* System hash blacklist.
   3 *
   4 * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
   5 * Written by David Howells (dhowells@redhat.com)
   6 */
   7
   8#define pr_fmt(fmt) "blacklist: "fmt
   9#include <linux/module.h>
  10#include <linux/slab.h>
  11#include <linux/key.h>
  12#include <linux/key-type.h>
  13#include <linux/sched.h>
  14#include <linux/ctype.h>
  15#include <linux/err.h>
  16#include <linux/seq_file.h>
  17#include <keys/system_keyring.h>
  18#include "blacklist.h"
  19
  20static struct key *blacklist_keyring;
  21
  22/*
  23 * The description must be a type prefix, a colon and then an even number of
  24 * hex digits.  The hash is kept in the description.
  25 */
  26static int blacklist_vet_description(const char *desc)
  27{
  28        int n = 0;
  29
  30        if (*desc == ':')
  31                return -EINVAL;
  32        for (; *desc; desc++)
  33                if (*desc == ':')
  34                        goto found_colon;
  35        return -EINVAL;
  36
  37found_colon:
  38        desc++;
  39        for (; *desc; desc++) {
  40                if (!isxdigit(*desc))
  41                        return -EINVAL;
  42                n++;
  43        }
  44
  45        if (n == 0 || n & 1)
  46                return -EINVAL;
  47        return 0;
  48}
  49
  50/*
  51 * The hash to be blacklisted is expected to be in the description.  There will
  52 * be no payload.
  53 */
  54static int blacklist_preparse(struct key_preparsed_payload *prep)
  55{
  56        if (prep->datalen > 0)
  57                return -EINVAL;
  58        return 0;
  59}
  60
  61static void blacklist_free_preparse(struct key_preparsed_payload *prep)
  62{
  63}
  64
  65static void blacklist_describe(const struct key *key, struct seq_file *m)
  66{
  67        seq_puts(m, key->description);
  68}
  69
  70static struct key_type key_type_blacklist = {
  71        .name                   = "blacklist",
  72        .vet_description        = blacklist_vet_description,
  73        .preparse               = blacklist_preparse,
  74        .free_preparse          = blacklist_free_preparse,
  75        .instantiate            = generic_key_instantiate,
  76        .describe               = blacklist_describe,
  77};
  78
  79/**
  80 * mark_hash_blacklisted - Add a hash to the system blacklist
  81 * @hash - The hash as a hex string with a type prefix (eg. "tbs:23aa429783")
  82 */
  83int mark_hash_blacklisted(const char *hash)
  84{
  85        key_ref_t key;
  86
  87        key = key_create_or_update(make_key_ref(blacklist_keyring, true),
  88                                   "blacklist",
  89                                   hash,
  90                                   NULL,
  91                                   0,
  92                                   ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
  93                                    KEY_USR_VIEW),
  94                                   KEY_ALLOC_NOT_IN_QUOTA |
  95                                   KEY_ALLOC_BUILT_IN);
  96        if (IS_ERR(key)) {
  97                pr_err("Problem blacklisting hash (%ld)\n", PTR_ERR(key));
  98                return PTR_ERR(key);
  99        }
 100        return 0;
 101}
 102
 103/**
 104 * is_hash_blacklisted - Determine if a hash is blacklisted
 105 * @hash: The hash to be checked as a binary blob
 106 * @hash_len: The length of the binary hash
 107 * @type: Type of hash
 108 */
 109int is_hash_blacklisted(const u8 *hash, size_t hash_len, const char *type)
 110{
 111        key_ref_t kref;
 112        size_t type_len = strlen(type);
 113        char *buffer, *p;
 114        int ret = 0;
 115
 116        buffer = kmalloc(type_len + 1 + hash_len * 2 + 1, GFP_KERNEL);
 117        if (!buffer)
 118                return -ENOMEM;
 119        p = memcpy(buffer, type, type_len);
 120        p += type_len;
 121        *p++ = ':';
 122        bin2hex(p, hash, hash_len);
 123        p += hash_len * 2;
 124        *p = 0;
 125
 126        kref = keyring_search(make_key_ref(blacklist_keyring, true),
 127                              &key_type_blacklist, buffer);
 128        if (!IS_ERR(kref)) {
 129                key_ref_put(kref);
 130                ret = -EKEYREJECTED;
 131        }
 132
 133        kfree(buffer);
 134        return ret;
 135}
 136EXPORT_SYMBOL_GPL(is_hash_blacklisted);
 137
 138/*
 139 * Initialise the blacklist
 140 */
 141static int __init blacklist_init(void)
 142{
 143        const char *const *bl;
 144
 145        if (register_key_type(&key_type_blacklist) < 0)
 146                panic("Can't allocate system blacklist key type\n");
 147
 148        blacklist_keyring =
 149                keyring_alloc(".blacklist",
 150                              KUIDT_INIT(0), KGIDT_INIT(0),
 151                              current_cred(),
 152                              (KEY_POS_ALL & ~KEY_POS_SETATTR) |
 153                              KEY_USR_VIEW | KEY_USR_READ |
 154                              KEY_USR_SEARCH,
 155                              KEY_ALLOC_NOT_IN_QUOTA |
 156                              KEY_FLAG_KEEP,
 157                              NULL, NULL);
 158        if (IS_ERR(blacklist_keyring))
 159                panic("Can't allocate system blacklist keyring\n");
 160
 161        for (bl = blacklist_hashes; *bl; bl++)
 162                if (mark_hash_blacklisted(*bl) < 0)
 163                        pr_err("- blacklisting failed\n");
 164        return 0;
 165}
 166
 167/*
 168 * Must be initialised before we try and load the keys into the keyring.
 169 */
 170device_initcall(blacklist_init);
 171