cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

digsig.c (5248B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2011 Intel Corporation
      4 *
      5 * Author:
      6 * Dmitry Kasatkin <dmitry.kasatkin@intel.com>
      7 */
      8
      9#include <linux/err.h>
     10#include <linux/sched.h>
     11#include <linux/slab.h>
     12#include <linux/cred.h>
     13#include <linux/kernel_read_file.h>
     14#include <linux/key-type.h>
     15#include <linux/digsig.h>
     16#include <linux/vmalloc.h>
     17#include <crypto/public_key.h>
     18#include <keys/system_keyring.h>
     19
     20#include "integrity.h"
     21
     22static struct key *keyring[INTEGRITY_KEYRING_MAX];
     23
     24static const char * const keyring_name[INTEGRITY_KEYRING_MAX] = {
     25#ifndef CONFIG_INTEGRITY_TRUSTED_KEYRING
     26	"_evm",
     27	"_ima",
     28#else
     29	".evm",
     30	".ima",
     31#endif
     32	".platform",
     33	".machine",
     34};
     35
     36#ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
     37#define restrict_link_to_ima restrict_link_by_builtin_and_secondary_trusted
     38#else
     39#define restrict_link_to_ima restrict_link_by_builtin_trusted
     40#endif
     41
     42static struct key *integrity_keyring_from_id(const unsigned int id)
     43{
     44	if (id >= INTEGRITY_KEYRING_MAX)
     45		return ERR_PTR(-EINVAL);
     46
     47	if (!keyring[id]) {
     48		keyring[id] =
     49			request_key(&key_type_keyring, keyring_name[id], NULL);
     50		if (IS_ERR(keyring[id])) {
     51			int err = PTR_ERR(keyring[id]);
     52			pr_err("no %s keyring: %d\n", keyring_name[id], err);
     53			keyring[id] = NULL;
     54			return ERR_PTR(err);
     55		}
     56	}
     57
     58	return keyring[id];
     59}
     60
     61int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
     62			    const char *digest, int digestlen)
     63{
     64	struct key *keyring;
     65
     66	if (siglen < 2)
     67		return -EINVAL;
     68
     69	keyring = integrity_keyring_from_id(id);
     70	if (IS_ERR(keyring))
     71		return PTR_ERR(keyring);
     72
     73	switch (sig[1]) {
     74	case 1:
     75		/* v1 API expect signature without xattr type */
     76		return digsig_verify(keyring, sig + 1, siglen - 1, digest,
     77				     digestlen);
     78	case 2: /* regular file data hash based signature */
     79	case 3: /* struct ima_file_id data based signature */
     80		return asymmetric_verify(keyring, sig, siglen, digest,
     81					 digestlen);
     82	}
     83
     84	return -EOPNOTSUPP;
     85}
     86
     87int integrity_modsig_verify(const unsigned int id, const struct modsig *modsig)
     88{
     89	struct key *keyring;
     90
     91	keyring = integrity_keyring_from_id(id);
     92	if (IS_ERR(keyring))
     93		return PTR_ERR(keyring);
     94
     95	return ima_modsig_verify(keyring, modsig);
     96}
     97
     98static int __init __integrity_init_keyring(const unsigned int id,
     99					   key_perm_t perm,
    100					   struct key_restriction *restriction)
    101{
    102	const struct cred *cred = current_cred();
    103	int err = 0;
    104
    105	keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
    106				    KGIDT_INIT(0), cred, perm,
    107				    KEY_ALLOC_NOT_IN_QUOTA, restriction, NULL);
    108	if (IS_ERR(keyring[id])) {
    109		err = PTR_ERR(keyring[id]);
    110		pr_info("Can't allocate %s keyring (%d)\n",
    111			keyring_name[id], err);
    112		keyring[id] = NULL;
    113	} else {
    114		if (id == INTEGRITY_KEYRING_PLATFORM)
    115			set_platform_trusted_keys(keyring[id]);
    116		if (id == INTEGRITY_KEYRING_MACHINE && trust_moklist())
    117			set_machine_trusted_keys(keyring[id]);
    118		if (id == INTEGRITY_KEYRING_IMA)
    119			load_module_cert(keyring[id]);
    120	}
    121
    122	return err;
    123}
    124
    125int __init integrity_init_keyring(const unsigned int id)
    126{
    127	struct key_restriction *restriction;
    128	key_perm_t perm;
    129
    130	perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW
    131		| KEY_USR_READ | KEY_USR_SEARCH;
    132
    133	if (id == INTEGRITY_KEYRING_PLATFORM ||
    134	    id == INTEGRITY_KEYRING_MACHINE) {
    135		restriction = NULL;
    136		goto out;
    137	}
    138
    139	if (!IS_ENABLED(CONFIG_INTEGRITY_TRUSTED_KEYRING))
    140		return 0;
    141
    142	restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
    143	if (!restriction)
    144		return -ENOMEM;
    145
    146	restriction->check = restrict_link_to_ima;
    147
    148	/*
    149	 * MOK keys can only be added through a read-only runtime services
    150	 * UEFI variable during boot. No additional keys shall be allowed to
    151	 * load into the machine keyring following init from userspace.
    152	 */
    153	if (id != INTEGRITY_KEYRING_MACHINE)
    154		perm |= KEY_USR_WRITE;
    155
    156out:
    157	return __integrity_init_keyring(id, perm, restriction);
    158}
    159
    160static int __init integrity_add_key(const unsigned int id, const void *data,
    161				    off_t size, key_perm_t perm)
    162{
    163	key_ref_t key;
    164	int rc = 0;
    165
    166	if (!keyring[id])
    167		return -EINVAL;
    168
    169	key = key_create_or_update(make_key_ref(keyring[id], 1), "asymmetric",
    170				   NULL, data, size, perm,
    171				   KEY_ALLOC_NOT_IN_QUOTA);
    172	if (IS_ERR(key)) {
    173		rc = PTR_ERR(key);
    174		pr_err("Problem loading X.509 certificate %d\n", rc);
    175	} else {
    176		pr_notice("Loaded X.509 cert '%s'\n",
    177			  key_ref_to_ptr(key)->description);
    178		key_ref_put(key);
    179	}
    180
    181	return rc;
    182
    183}
    184
    185int __init integrity_load_x509(const unsigned int id, const char *path)
    186{
    187	void *data = NULL;
    188	size_t size;
    189	int rc;
    190	key_perm_t perm;
    191
    192	rc = kernel_read_file_from_path(path, 0, &data, INT_MAX, NULL,
    193					READING_X509_CERTIFICATE);
    194	if (rc < 0) {
    195		pr_err("Unable to open file: %s (%d)", path, rc);
    196		return rc;
    197	}
    198	size = rc;
    199
    200	perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ;
    201
    202	pr_info("Loading X.509 certificate: %s\n", path);
    203	rc = integrity_add_key(id, (const void *)data, size, perm);
    204
    205	vfree(data);
    206	return rc;
    207}
    208
    209int __init integrity_load_cert(const unsigned int id, const char *source,
    210			       const void *data, size_t len, key_perm_t perm)
    211{
    212	if (!data)
    213		return -EINVAL;
    214
    215	pr_info("Loading X.509 certificate: %s\n", source);
    216	return integrity_add_key(id, data, len, perm);
    217}