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

dm-verity-verify-sig.c (3193B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2019 Microsoft Corporation.
      4 *
      5 * Author:  Jaskaran Singh Khurana <jaskarankhurana@linux.microsoft.com>
      6 *
      7 */
      8#include <linux/device-mapper.h>
      9#include <linux/verification.h>
     10#include <keys/user-type.h>
     11#include <linux/module.h>
     12#include "dm-verity.h"
     13#include "dm-verity-verify-sig.h"
     14
     15#define DM_VERITY_VERIFY_ERR(s) DM_VERITY_ROOT_HASH_VERIFICATION " " s
     16
     17static bool require_signatures;
     18module_param(require_signatures, bool, 0444);
     19MODULE_PARM_DESC(require_signatures,
     20		"Verify the roothash of dm-verity hash tree");
     21
     22#define DM_VERITY_IS_SIG_FORCE_ENABLED() \
     23	(require_signatures != false)
     24
     25bool verity_verify_is_sig_opt_arg(const char *arg_name)
     26{
     27	return (!strcasecmp(arg_name,
     28			    DM_VERITY_ROOT_HASH_VERIFICATION_OPT_SIG_KEY));
     29}
     30
     31static int verity_verify_get_sig_from_key(const char *key_desc,
     32					struct dm_verity_sig_opts *sig_opts)
     33{
     34	struct key *key;
     35	const struct user_key_payload *ukp;
     36	int ret = 0;
     37
     38	key = request_key(&key_type_user,
     39			key_desc, NULL);
     40	if (IS_ERR(key))
     41		return PTR_ERR(key);
     42
     43	down_read(&key->sem);
     44
     45	ukp = user_key_payload_locked(key);
     46	if (!ukp) {
     47		ret = -EKEYREVOKED;
     48		goto end;
     49	}
     50
     51	sig_opts->sig = kmalloc(ukp->datalen, GFP_KERNEL);
     52	if (!sig_opts->sig) {
     53		ret = -ENOMEM;
     54		goto end;
     55	}
     56	sig_opts->sig_size = ukp->datalen;
     57
     58	memcpy(sig_opts->sig, ukp->data, sig_opts->sig_size);
     59
     60end:
     61	up_read(&key->sem);
     62	key_put(key);
     63
     64	return ret;
     65}
     66
     67int verity_verify_sig_parse_opt_args(struct dm_arg_set *as,
     68				     struct dm_verity *v,
     69				     struct dm_verity_sig_opts *sig_opts,
     70				     unsigned int *argc,
     71				     const char *arg_name)
     72{
     73	struct dm_target *ti = v->ti;
     74	int ret = 0;
     75	const char *sig_key = NULL;
     76
     77	if (!*argc) {
     78		ti->error = DM_VERITY_VERIFY_ERR("Signature key not specified");
     79		return -EINVAL;
     80	}
     81
     82	sig_key = dm_shift_arg(as);
     83	(*argc)--;
     84
     85	ret = verity_verify_get_sig_from_key(sig_key, sig_opts);
     86	if (ret < 0)
     87		ti->error = DM_VERITY_VERIFY_ERR("Invalid key specified");
     88
     89	v->signature_key_desc = kstrdup(sig_key, GFP_KERNEL);
     90	if (!v->signature_key_desc)
     91		return -ENOMEM;
     92
     93	return ret;
     94}
     95
     96/*
     97 * verify_verify_roothash - Verify the root hash of the verity hash device
     98 *			     using builtin trusted keys.
     99 *
    100 * @root_hash: For verity, the roothash/data to be verified.
    101 * @root_hash_len: Size of the roothash/data to be verified.
    102 * @sig_data: The trusted signature that verifies the roothash/data.
    103 * @sig_len: Size of the signature.
    104 *
    105 */
    106int verity_verify_root_hash(const void *root_hash, size_t root_hash_len,
    107			    const void *sig_data, size_t sig_len)
    108{
    109	int ret;
    110
    111	if (!root_hash || root_hash_len == 0)
    112		return -EINVAL;
    113
    114	if (!sig_data  || sig_len == 0) {
    115		if (DM_VERITY_IS_SIG_FORCE_ENABLED())
    116			return -ENOKEY;
    117		else
    118			return 0;
    119	}
    120
    121	ret = verify_pkcs7_signature(root_hash, root_hash_len, sig_data,
    122				sig_len,
    123#ifdef CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG_SECONDARY_KEYRING
    124				VERIFY_USE_SECONDARY_KEYRING,
    125#else
    126				NULL,
    127#endif
    128				VERIFYING_UNSPECIFIED_SIGNATURE, NULL, NULL);
    129
    130	return ret;
    131}
    132
    133void verity_verify_sig_opts_cleanup(struct dm_verity_sig_opts *sig_opts)
    134{
    135	kfree(sig_opts->sig);
    136	sig_opts->sig = NULL;
    137	sig_opts->sig_size = 0;
    138}