![Horia Geantă](/assets/img/avatar_default.png)
Offload split key generation in CAAM engine, using DKP. DKP is supported starting with Era 6. Note that the way assoclen is transmitted from the job descriptor to the shared descriptor changes - DPOVRD register is used instead of MATH3 (where available), since DKP protocol thrashes the MATH registers. The replacement of MDHA split key generation with DKP has the side effect of the crypto engine writing the authentication key, and thus the DMA mapping direction for the buffer holding the key has to change from DMA_TO_DEVICE to DMA_BIDIRECTIONAL. There are two cases: -key is inlined in descriptor - descriptor buffer mapping changes -key is referenced - key buffer mapping changes Signed-off-by: Horia Geantă <horia.geanta@nxp.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
141 lines
3.8 KiB
C
141 lines
3.8 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* CAAM/SEC 4.x functions for handling key-generation jobs
|
|
*
|
|
* Copyright 2008-2011 Freescale Semiconductor, Inc.
|
|
*
|
|
*/
|
|
#include "compat.h"
|
|
#include "jr.h"
|
|
#include "error.h"
|
|
#include "desc_constr.h"
|
|
#include "key_gen.h"
|
|
|
|
void split_key_done(struct device *dev, u32 *desc, u32 err,
|
|
void *context)
|
|
{
|
|
struct split_key_result *res = context;
|
|
|
|
#ifdef DEBUG
|
|
dev_err(dev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
|
|
#endif
|
|
|
|
if (err)
|
|
caam_jr_strstatus(dev, err);
|
|
|
|
res->err = err;
|
|
|
|
complete(&res->completion);
|
|
}
|
|
EXPORT_SYMBOL(split_key_done);
|
|
/*
|
|
get a split ipad/opad key
|
|
|
|
Split key generation-----------------------------------------------
|
|
|
|
[00] 0xb0810008 jobdesc: stidx=1 share=never len=8
|
|
[01] 0x04000014 key: class2->keyreg len=20
|
|
@0xffe01000
|
|
[03] 0x84410014 operation: cls2-op sha1 hmac init dec
|
|
[04] 0x24940000 fifold: class2 msgdata-last2 len=0 imm
|
|
[05] 0xa4000001 jump: class2 local all ->1 [06]
|
|
[06] 0x64260028 fifostr: class2 mdsplit-jdk len=40
|
|
@0xffe04000
|
|
*/
|
|
int gen_split_key(struct device *jrdev, u8 *key_out,
|
|
struct alginfo * const adata, const u8 *key_in, u32 keylen,
|
|
int max_keylen)
|
|
{
|
|
u32 *desc;
|
|
struct split_key_result result;
|
|
dma_addr_t dma_addr_in, dma_addr_out;
|
|
int ret = -ENOMEM;
|
|
|
|
adata->keylen = split_key_len(adata->algtype & OP_ALG_ALGSEL_MASK);
|
|
adata->keylen_pad = split_key_pad_len(adata->algtype &
|
|
OP_ALG_ALGSEL_MASK);
|
|
|
|
#ifdef DEBUG
|
|
dev_err(jrdev, "split keylen %d split keylen padded %d\n",
|
|
adata->keylen, adata->keylen_pad);
|
|
print_hex_dump(KERN_ERR, "ctx.key@" __stringify(__LINE__)": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, key_in, keylen, 1);
|
|
#endif
|
|
|
|
if (adata->keylen_pad > max_keylen)
|
|
return -EINVAL;
|
|
|
|
desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
|
|
if (!desc) {
|
|
dev_err(jrdev, "unable to allocate key input memory\n");
|
|
return ret;
|
|
}
|
|
|
|
dma_addr_in = dma_map_single(jrdev, (void *)key_in, keylen,
|
|
DMA_TO_DEVICE);
|
|
if (dma_mapping_error(jrdev, dma_addr_in)) {
|
|
dev_err(jrdev, "unable to map key input memory\n");
|
|
goto out_free;
|
|
}
|
|
|
|
dma_addr_out = dma_map_single(jrdev, key_out, adata->keylen_pad,
|
|
DMA_FROM_DEVICE);
|
|
if (dma_mapping_error(jrdev, dma_addr_out)) {
|
|
dev_err(jrdev, "unable to map key output memory\n");
|
|
goto out_unmap_in;
|
|
}
|
|
|
|
init_job_desc(desc, 0);
|
|
append_key(desc, dma_addr_in, keylen, CLASS_2 | KEY_DEST_CLASS_REG);
|
|
|
|
/* Sets MDHA up into an HMAC-INIT */
|
|
append_operation(desc, (adata->algtype & OP_ALG_ALGSEL_MASK) |
|
|
OP_ALG_AAI_HMAC | OP_TYPE_CLASS2_ALG | OP_ALG_DECRYPT |
|
|
OP_ALG_AS_INIT);
|
|
|
|
/*
|
|
* do a FIFO_LOAD of zero, this will trigger the internal key expansion
|
|
* into both pads inside MDHA
|
|
*/
|
|
append_fifo_load_as_imm(desc, NULL, 0, LDST_CLASS_2_CCB |
|
|
FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2);
|
|
|
|
/*
|
|
* FIFO_STORE with the explicit split-key content store
|
|
* (0x26 output type)
|
|
*/
|
|
append_fifo_store(desc, dma_addr_out, adata->keylen,
|
|
LDST_CLASS_2_CCB | FIFOST_TYPE_SPLIT_KEK);
|
|
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, key_in, keylen, 1);
|
|
print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
|
#endif
|
|
|
|
result.err = 0;
|
|
init_completion(&result.completion);
|
|
|
|
ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result);
|
|
if (!ret) {
|
|
/* in progress */
|
|
wait_for_completion(&result.completion);
|
|
ret = result.err;
|
|
#ifdef DEBUG
|
|
print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
|
|
DUMP_PREFIX_ADDRESS, 16, 4, key_out,
|
|
adata->keylen_pad, 1);
|
|
#endif
|
|
}
|
|
|
|
dma_unmap_single(jrdev, dma_addr_out, adata->keylen_pad,
|
|
DMA_FROM_DEVICE);
|
|
out_unmap_in:
|
|
dma_unmap_single(jrdev, dma_addr_in, keylen, DMA_TO_DEVICE);
|
|
out_free:
|
|
kfree(desc);
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(gen_split_key);
|