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

blob_gen.c (5022B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2015 Pengutronix, Steffen Trumtrar <kernel@pengutronix.de>
      4 * Copyright (C) 2021 Pengutronix, Ahmad Fatoum <kernel@pengutronix.de>
      5 */
      6
      7#define pr_fmt(fmt) "caam blob_gen: " fmt
      8
      9#include <linux/device.h>
     10#include <soc/fsl/caam-blob.h>
     11
     12#include "compat.h"
     13#include "desc_constr.h"
     14#include "desc.h"
     15#include "error.h"
     16#include "intern.h"
     17#include "jr.h"
     18#include "regs.h"
     19
     20#define CAAM_BLOB_DESC_BYTES_MAX					\
     21	/* Command to initialize & stating length of descriptor */	\
     22	(CAAM_CMD_SZ +							\
     23	/* Command to append the key-modifier + key-modifier data */	\
     24	 CAAM_CMD_SZ + CAAM_BLOB_KEYMOD_LENGTH +			\
     25	/* Command to include input key + pointer to the input key */	\
     26	 CAAM_CMD_SZ + CAAM_PTR_SZ_MAX +				\
     27	/* Command to include output key + pointer to the output key */	\
     28	 CAAM_CMD_SZ + CAAM_PTR_SZ_MAX +				\
     29	/* Command describing the operation to perform */		\
     30	 CAAM_CMD_SZ)
     31
     32struct caam_blob_priv {
     33	struct device jrdev;
     34};
     35
     36struct caam_blob_job_result {
     37	int err;
     38	struct completion completion;
     39};
     40
     41static void caam_blob_job_done(struct device *dev, u32 *desc, u32 err, void *context)
     42{
     43	struct caam_blob_job_result *res = context;
     44	int ecode = 0;
     45
     46	dev_dbg(dev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
     47
     48	if (err)
     49		ecode = caam_jr_strstatus(dev, err);
     50
     51	res->err = ecode;
     52
     53	/*
     54	 * Upon completion, desc points to a buffer containing a CAAM job
     55	 * descriptor which encapsulates data into an externally-storable
     56	 * blob.
     57	 */
     58	complete(&res->completion);
     59}
     60
     61int caam_process_blob(struct caam_blob_priv *priv,
     62		      struct caam_blob_info *info, bool encap)
     63{
     64	struct caam_blob_job_result testres;
     65	struct device *jrdev = &priv->jrdev;
     66	dma_addr_t dma_in, dma_out;
     67	int op = OP_PCLID_BLOB;
     68	size_t output_len;
     69	u32 *desc;
     70	int ret;
     71
     72	if (info->key_mod_len > CAAM_BLOB_KEYMOD_LENGTH)
     73		return -EINVAL;
     74
     75	if (encap) {
     76		op |= OP_TYPE_ENCAP_PROTOCOL;
     77		output_len = info->input_len + CAAM_BLOB_OVERHEAD;
     78	} else {
     79		op |= OP_TYPE_DECAP_PROTOCOL;
     80		output_len = info->input_len - CAAM_BLOB_OVERHEAD;
     81	}
     82
     83	desc = kzalloc(CAAM_BLOB_DESC_BYTES_MAX, GFP_KERNEL | GFP_DMA);
     84	if (!desc)
     85		return -ENOMEM;
     86
     87	dma_in = dma_map_single(jrdev, info->input, info->input_len,
     88				DMA_TO_DEVICE);
     89	if (dma_mapping_error(jrdev, dma_in)) {
     90		dev_err(jrdev, "unable to map input DMA buffer\n");
     91		ret = -ENOMEM;
     92		goto out_free;
     93	}
     94
     95	dma_out = dma_map_single(jrdev, info->output, output_len,
     96				 DMA_FROM_DEVICE);
     97	if (dma_mapping_error(jrdev, dma_out)) {
     98		dev_err(jrdev, "unable to map output DMA buffer\n");
     99		ret = -ENOMEM;
    100		goto out_unmap_in;
    101	}
    102
    103	/*
    104	 * A data blob is encrypted using a blob key (BK); a random number.
    105	 * The BK is used as an AES-CCM key. The initial block (B0) and the
    106	 * initial counter (Ctr0) are generated automatically and stored in
    107	 * Class 1 Context DWords 0+1+2+3. The random BK is stored in the
    108	 * Class 1 Key Register. Operation Mode is set to AES-CCM.
    109	 */
    110
    111	init_job_desc(desc, 0);
    112	append_key_as_imm(desc, info->key_mod, info->key_mod_len,
    113			  info->key_mod_len, CLASS_2 | KEY_DEST_CLASS_REG);
    114	append_seq_in_ptr_intlen(desc, dma_in, info->input_len, 0);
    115	append_seq_out_ptr_intlen(desc, dma_out, output_len, 0);
    116	append_operation(desc, op);
    117
    118	print_hex_dump_debug("data@"__stringify(__LINE__)": ",
    119			     DUMP_PREFIX_ADDRESS, 16, 1, info->input,
    120			     info->input_len, false);
    121	print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ",
    122			     DUMP_PREFIX_ADDRESS, 16, 1, desc,
    123			     desc_bytes(desc), false);
    124
    125	testres.err = 0;
    126	init_completion(&testres.completion);
    127
    128	ret = caam_jr_enqueue(jrdev, desc, caam_blob_job_done, &testres);
    129	if (ret == -EINPROGRESS) {
    130		wait_for_completion(&testres.completion);
    131		ret = testres.err;
    132		print_hex_dump_debug("output@"__stringify(__LINE__)": ",
    133				     DUMP_PREFIX_ADDRESS, 16, 1, info->output,
    134				     output_len, false);
    135	}
    136
    137	if (ret == 0)
    138		info->output_len = output_len;
    139
    140	dma_unmap_single(jrdev, dma_out, output_len, DMA_FROM_DEVICE);
    141out_unmap_in:
    142	dma_unmap_single(jrdev, dma_in, info->input_len, DMA_TO_DEVICE);
    143out_free:
    144	kfree(desc);
    145
    146	return ret;
    147}
    148EXPORT_SYMBOL(caam_process_blob);
    149
    150struct caam_blob_priv *caam_blob_gen_init(void)
    151{
    152	struct caam_drv_private *ctrlpriv;
    153	struct device *jrdev;
    154
    155	/*
    156	 * caam_blob_gen_init() may expectedly fail with -ENODEV, e.g. when
    157	 * CAAM driver didn't probe or when SoC lacks BLOB support. An
    158	 * error would be harsh in this case, so we stick to info level.
    159	 */
    160
    161	jrdev = caam_jr_alloc();
    162	if (IS_ERR(jrdev)) {
    163		pr_info("job ring requested, but none currently available\n");
    164		return ERR_PTR(-ENODEV);
    165	}
    166
    167	ctrlpriv = dev_get_drvdata(jrdev->parent);
    168	if (!ctrlpriv->blob_present) {
    169		dev_info(jrdev, "no hardware blob generation support\n");
    170		caam_jr_free(jrdev);
    171		return ERR_PTR(-ENODEV);
    172	}
    173
    174	return container_of(jrdev, struct caam_blob_priv, jrdev);
    175}
    176EXPORT_SYMBOL(caam_blob_gen_init);
    177
    178void caam_blob_gen_exit(struct caam_blob_priv *priv)
    179{
    180	caam_jr_free(&priv->jrdev);
    181}
    182EXPORT_SYMBOL(caam_blob_gen_exit);