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_asymmetric.c (3852B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2013 Intel Corporation
      4 *
      5 * Author:
      6 * Dmitry Kasatkin <dmitry.kasatkin@intel.com>
      7 */
      8
      9#include <linux/err.h>
     10#include <linux/ratelimit.h>
     11#include <linux/key-type.h>
     12#include <crypto/public_key.h>
     13#include <crypto/hash_info.h>
     14#include <keys/asymmetric-type.h>
     15#include <keys/system_keyring.h>
     16
     17#include "integrity.h"
     18
     19/*
     20 * Request an asymmetric key.
     21 */
     22static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
     23{
     24	struct key *key;
     25	char name[12];
     26
     27	sprintf(name, "id:%08x", keyid);
     28
     29	pr_debug("key search: \"%s\"\n", name);
     30
     31	key = get_ima_blacklist_keyring();
     32	if (key) {
     33		key_ref_t kref;
     34
     35		kref = keyring_search(make_key_ref(key, 1),
     36				      &key_type_asymmetric, name, true);
     37		if (!IS_ERR(kref)) {
     38			pr_err("Key '%s' is in ima_blacklist_keyring\n", name);
     39			return ERR_PTR(-EKEYREJECTED);
     40		}
     41	}
     42
     43	if (keyring) {
     44		/* search in specific keyring */
     45		key_ref_t kref;
     46
     47		kref = keyring_search(make_key_ref(keyring, 1),
     48				      &key_type_asymmetric, name, true);
     49		if (IS_ERR(kref))
     50			key = ERR_CAST(kref);
     51		else
     52			key = key_ref_to_ptr(kref);
     53	} else {
     54		key = request_key(&key_type_asymmetric, name, NULL);
     55	}
     56
     57	if (IS_ERR(key)) {
     58		if (keyring)
     59			pr_err_ratelimited("Request for unknown key '%s' in '%s' keyring. err %ld\n",
     60					   name, keyring->description,
     61					   PTR_ERR(key));
     62		else
     63			pr_err_ratelimited("Request for unknown key '%s' err %ld\n",
     64					   name, PTR_ERR(key));
     65
     66		switch (PTR_ERR(key)) {
     67			/* Hide some search errors */
     68		case -EACCES:
     69		case -ENOTDIR:
     70		case -EAGAIN:
     71			return ERR_PTR(-ENOKEY);
     72		default:
     73			return key;
     74		}
     75	}
     76
     77	pr_debug("%s() = 0 [%x]\n", __func__, key_serial(key));
     78
     79	return key;
     80}
     81
     82int asymmetric_verify(struct key *keyring, const char *sig,
     83		      int siglen, const char *data, int datalen)
     84{
     85	struct public_key_signature pks;
     86	struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig;
     87	const struct public_key *pk;
     88	struct key *key;
     89	int ret;
     90
     91	if (siglen <= sizeof(*hdr))
     92		return -EBADMSG;
     93
     94	siglen -= sizeof(*hdr);
     95
     96	if (siglen != be16_to_cpu(hdr->sig_size))
     97		return -EBADMSG;
     98
     99	if (hdr->hash_algo >= HASH_ALGO__LAST)
    100		return -ENOPKG;
    101
    102	key = request_asymmetric_key(keyring, be32_to_cpu(hdr->keyid));
    103	if (IS_ERR(key))
    104		return PTR_ERR(key);
    105
    106	memset(&pks, 0, sizeof(pks));
    107
    108	pks.hash_algo = hash_algo_name[hdr->hash_algo];
    109
    110	pk = asymmetric_key_public_key(key);
    111	pks.pkey_algo = pk->pkey_algo;
    112	if (!strcmp(pk->pkey_algo, "rsa")) {
    113		pks.encoding = "pkcs1";
    114	} else if (!strncmp(pk->pkey_algo, "ecdsa-", 6)) {
    115		/* edcsa-nist-p192 etc. */
    116		pks.encoding = "x962";
    117	} else if (!strcmp(pk->pkey_algo, "ecrdsa") ||
    118		   !strcmp(pk->pkey_algo, "sm2")) {
    119		pks.encoding = "raw";
    120	} else {
    121		ret = -ENOPKG;
    122		goto out;
    123	}
    124
    125	pks.digest = (u8 *)data;
    126	pks.digest_size = datalen;
    127	pks.s = hdr->sig;
    128	pks.s_size = siglen;
    129	ret = verify_signature(key, &pks);
    130out:
    131	key_put(key);
    132	pr_debug("%s() = %d\n", __func__, ret);
    133	return ret;
    134}
    135
    136/**
    137 * integrity_kernel_module_request - prevent crypto-pkcs1pad(rsa,*) requests
    138 * @kmod_name: kernel module name
    139 *
    140 * We have situation, when public_key_verify_signature() in case of RSA
    141 * algorithm use alg_name to store internal information in order to
    142 * construct an algorithm on the fly, but crypto_larval_lookup() will try
    143 * to use alg_name in order to load kernel module with same name.
    144 * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules,
    145 * we are safe to fail such module request from crypto_larval_lookup().
    146 *
    147 * In this way we prevent modprobe execution during digsig verification
    148 * and avoid possible deadlock if modprobe and/or it's dependencies
    149 * also signed with digsig.
    150 */
    151int integrity_kernel_module_request(char *kmod_name)
    152{
    153	if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0)
    154		return -EINVAL;
    155
    156	return 0;
    157}