162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * CAAM/SEC 4.x functions for handling key-generation jobs 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2008-2011 Freescale Semiconductor, Inc. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci#include "compat.h" 962306a36Sopenharmony_ci#include "jr.h" 1062306a36Sopenharmony_ci#include "error.h" 1162306a36Sopenharmony_ci#include "desc_constr.h" 1262306a36Sopenharmony_ci#include "key_gen.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_civoid split_key_done(struct device *dev, u32 *desc, u32 err, 1562306a36Sopenharmony_ci void *context) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci struct split_key_result *res = context; 1862306a36Sopenharmony_ci int ecode = 0; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci dev_dbg(dev, "%s %d: err 0x%x\n", __func__, __LINE__, err); 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci if (err) 2362306a36Sopenharmony_ci ecode = caam_jr_strstatus(dev, err); 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci res->err = ecode; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci complete(&res->completion); 2862306a36Sopenharmony_ci} 2962306a36Sopenharmony_ciEXPORT_SYMBOL(split_key_done); 3062306a36Sopenharmony_ci/* 3162306a36Sopenharmony_ciget a split ipad/opad key 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ciSplit key generation----------------------------------------------- 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci[00] 0xb0810008 jobdesc: stidx=1 share=never len=8 3662306a36Sopenharmony_ci[01] 0x04000014 key: class2->keyreg len=20 3762306a36Sopenharmony_ci @0xffe01000 3862306a36Sopenharmony_ci[03] 0x84410014 operation: cls2-op sha1 hmac init dec 3962306a36Sopenharmony_ci[04] 0x24940000 fifold: class2 msgdata-last2 len=0 imm 4062306a36Sopenharmony_ci[05] 0xa4000001 jump: class2 local all ->1 [06] 4162306a36Sopenharmony_ci[06] 0x64260028 fifostr: class2 mdsplit-jdk len=40 4262306a36Sopenharmony_ci @0xffe04000 4362306a36Sopenharmony_ci*/ 4462306a36Sopenharmony_ciint gen_split_key(struct device *jrdev, u8 *key_out, 4562306a36Sopenharmony_ci struct alginfo * const adata, const u8 *key_in, u32 keylen, 4662306a36Sopenharmony_ci int max_keylen) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci u32 *desc; 4962306a36Sopenharmony_ci struct split_key_result result; 5062306a36Sopenharmony_ci dma_addr_t dma_addr; 5162306a36Sopenharmony_ci unsigned int local_max; 5262306a36Sopenharmony_ci int ret = -ENOMEM; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci adata->keylen = split_key_len(adata->algtype & OP_ALG_ALGSEL_MASK); 5562306a36Sopenharmony_ci adata->keylen_pad = split_key_pad_len(adata->algtype & 5662306a36Sopenharmony_ci OP_ALG_ALGSEL_MASK); 5762306a36Sopenharmony_ci local_max = max(keylen, adata->keylen_pad); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci dev_dbg(jrdev, "split keylen %d split keylen padded %d\n", 6062306a36Sopenharmony_ci adata->keylen, adata->keylen_pad); 6162306a36Sopenharmony_ci print_hex_dump_debug("ctx.key@" __stringify(__LINE__)": ", 6262306a36Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, key_in, keylen, 1); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci if (local_max > max_keylen) 6562306a36Sopenharmony_ci return -EINVAL; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL); 6862306a36Sopenharmony_ci if (!desc) { 6962306a36Sopenharmony_ci dev_err(jrdev, "unable to allocate key input memory\n"); 7062306a36Sopenharmony_ci return ret; 7162306a36Sopenharmony_ci } 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci memcpy(key_out, key_in, keylen); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci dma_addr = dma_map_single(jrdev, key_out, local_max, DMA_BIDIRECTIONAL); 7662306a36Sopenharmony_ci if (dma_mapping_error(jrdev, dma_addr)) { 7762306a36Sopenharmony_ci dev_err(jrdev, "unable to map key memory\n"); 7862306a36Sopenharmony_ci goto out_free; 7962306a36Sopenharmony_ci } 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci init_job_desc(desc, 0); 8262306a36Sopenharmony_ci append_key(desc, dma_addr, keylen, CLASS_2 | KEY_DEST_CLASS_REG); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci /* Sets MDHA up into an HMAC-INIT */ 8562306a36Sopenharmony_ci append_operation(desc, (adata->algtype & OP_ALG_ALGSEL_MASK) | 8662306a36Sopenharmony_ci OP_ALG_AAI_HMAC | OP_TYPE_CLASS2_ALG | OP_ALG_DECRYPT | 8762306a36Sopenharmony_ci OP_ALG_AS_INIT); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci /* 9062306a36Sopenharmony_ci * do a FIFO_LOAD of zero, this will trigger the internal key expansion 9162306a36Sopenharmony_ci * into both pads inside MDHA 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_ci append_fifo_load_as_imm(desc, NULL, 0, LDST_CLASS_2_CCB | 9462306a36Sopenharmony_ci FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci /* 9762306a36Sopenharmony_ci * FIFO_STORE with the explicit split-key content store 9862306a36Sopenharmony_ci * (0x26 output type) 9962306a36Sopenharmony_ci */ 10062306a36Sopenharmony_ci append_fifo_store(desc, dma_addr, adata->keylen, 10162306a36Sopenharmony_ci LDST_CLASS_2_CCB | FIFOST_TYPE_SPLIT_KEK); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci print_hex_dump_debug("jobdesc@"__stringify(__LINE__)": ", 10462306a36Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 10562306a36Sopenharmony_ci 1); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci result.err = 0; 10862306a36Sopenharmony_ci init_completion(&result.completion); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result); 11162306a36Sopenharmony_ci if (ret == -EINPROGRESS) { 11262306a36Sopenharmony_ci /* in progress */ 11362306a36Sopenharmony_ci wait_for_completion(&result.completion); 11462306a36Sopenharmony_ci ret = result.err; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci print_hex_dump_debug("ctx.key@"__stringify(__LINE__)": ", 11762306a36Sopenharmony_ci DUMP_PREFIX_ADDRESS, 16, 4, key_out, 11862306a36Sopenharmony_ci adata->keylen_pad, 1); 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci dma_unmap_single(jrdev, dma_addr, local_max, DMA_BIDIRECTIONAL); 12262306a36Sopenharmony_ciout_free: 12362306a36Sopenharmony_ci kfree(desc); 12462306a36Sopenharmony_ci return ret; 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ciEXPORT_SYMBOL(gen_split_key); 127