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