soc: qcom: hwkm: Re-format cmd packet for system kdf

1. Fix to format context correctly as expected by
   hardware for system KDF.
   HWKM reverses bytes at a 8-byte boundary while getting
   the context from cryptolib. Reformat the context in the
   command packet in such a way that HWKM receives it in the
   correct order. Also, pad the context to a 8-byte multiple
   as the way HW would pad it is not expected.
2. Use context for FBE to match with the one
   for VTS test cases.

Change-Id: I3c13c91b0dfc85aef406b05694dbd22afb0b2e0b
Signed-off-by: Gaurav Kashyap <gaurkash@codeaurora.org>
This commit is contained in:
Gaurav Kashyap 2020-06-25 20:47:05 -07:00
commit fd16bf9689
2 changed files with 58 additions and 23 deletions

View file

@ -9,6 +9,7 @@
#include <linux/crypto-qti-common.h>
#include <linux/hwkm.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include "crypto-qti-ice-regs.h"
#include "crypto-qti-platform.h"
@ -19,6 +20,8 @@
#define QTI_HWKM_INIT_DONE 0x1
#define SLOT_EMPTY_ERROR 0x1000
#define INLINECRYPT_CTX "inline encryption key"
#define BYTE_ORDER_VAL 8
union crypto_cfg {
__le32 regval[2];
@ -65,19 +68,10 @@ int crypto_qti_program_key(struct crypto_vops_qti_entry *ice_entry,
.km_by_nsec_allowed = true,
};
struct hwkm_bsve bsve_kdf = {
.enabled = false,
.enabled = true,
.km_swc_en = true,
.km_child_key_policy_en = true,
};
u8 ctx[] = {
0xee, 0xb6, 0xa4, 0xc8, 0x6f, 0x22, 0x5f, 0xda,
0x18, 0xff, 0x61, 0x07, 0xfb, 0x88, 0x17, 0x7f,
0xe4, 0x89, 0x8f, 0xed, 0xdb, 0x0c, 0x68, 0xb2,
0x18, 0xe7, 0x58, 0xd0, 0xf7, 0x79, 0x61, 0xad,
0x77, 0xc6, 0x4d, 0x2b, 0x53, 0x93, 0x4f, 0x34,
0xaf, 0x51, 0xab, 0xda, 0x24, 0xa0, 0xa4, 0x76,
0xf4, 0x09, 0xed, 0xa3, 0x2c, 0xa1, 0x8b, 0xcd,
0x01, 0xe7, 0x0a, 0x3e, 0x9d, 0x73, 0xac, 0x96,
};
union crypto_cfg cfg;
if ((key->size) <= RAW_SECRET_SIZE) {
@ -143,8 +137,9 @@ int crypto_qti_program_key(struct crypto_vops_qti_entry *ice_entry,
cmd_kdf.kdf.kdk = GP_KEYSLOT;
cmd_kdf.kdf.policy = policy_kdf;
cmd_kdf.kdf.bsve = bsve_kdf;
cmd_kdf.kdf.sz = 64;
memcpy(cmd_kdf.kdf.ctx, ctx, HWKM_MAX_CTX_SIZE);
cmd_kdf.kdf.sz = round_up(strlen(INLINECRYPT_CTX), BYTE_ORDER_VAL);
memset(cmd_kdf.kdf.ctx, 0, HWKM_MAX_CTX_SIZE);
memcpy(cmd_kdf.kdf.ctx, INLINECRYPT_CTX, strlen(INLINECRYPT_CTX));
memset(&cfg, 0, sizeof(cfg));
cfg.dusize = data_unit_mask;

View file

@ -49,6 +49,7 @@ for (retries = 0; !(cond) && (retries < MAX_RETRIES); retries++)
#define ICEMEM_SLAVE_TPKEY_VAL 0x192
#define ICEMEM_SLAVE_TPKEY_SLOT 0x92
#define KM_MASTER_TPKEY_SLOT 10
#define BYTE_ORDER_VAL 8
struct hwkm_clk_info {
struct list_head list;
@ -436,15 +437,38 @@ static void deserialize_policy(struct hwkm_key_policy *out,
out->km_by_spu_allowed = policy->key_management_by_spu_allowed;
}
static void reverse_key(u8 *key, size_t keylen)
static void reverse_bytes(u8 *bytes, size_t len)
{
size_t left = 0;
size_t right = 0;
for (left = 0, right = keylen - 1; left < right; left++, right--) {
key[left] ^= key[right];
key[right] ^= key[left];
key[left] ^= key[right];
for (left = 0, right = len - 1; left < right; left++, right--) {
bytes[left] ^= bytes[right];
bytes[right] ^= bytes[left];
bytes[left] ^= bytes[right];
}
}
static void reorder_ctx(u8 *ctx, size_t ctxlen)
{
int i = 0;
int len = 0;
len = ctxlen / BYTE_ORDER_VAL;
/* Reverse ctx at 8 byte boundary */
for (i = 0; i < len; i++)
reverse_bytes(ctx + i*BYTE_ORDER_VAL, BYTE_ORDER_VAL);
/*
* If context is not a multiple of 8 bytes, reverse the last bytes
* only. This simulates prepending the last 8 bytes with zeroes,
* and then reversing the 8 bytes.
*/
if (ctxlen % BYTE_ORDER_VAL != 0) {
reverse_bytes(ctx + len*BYTE_ORDER_VAL,
ctxlen % BYTE_ORDER_VAL);
}
}
@ -590,6 +614,15 @@ static int qti_handle_system_kdf(const struct hwkm_cmd *cmd_in,
serialize_policy(&policy, &cmd_in->kdf.policy);
/*
* If context is not a multiple of 8 bytes, but a multiple
* of 4 bytes, add a zero word at the end, to have a context multiple
* of 8 bytes. This is to facilitate the context reordering that will
* happen later
*/
if ((cmd_in->kdf.sz) % BYTE_ORDER_VAL == (BYTE_ORDER_VAL/2))
operation.context_len += 1;
WRITE_TO_KDF_PACKET(cmd_ptr, &operation, OPERATION_INFO_LENGTH);
WRITE_TO_KDF_PACKET(cmd_ptr, &policy, KEY_POLICY_LENGTH);
@ -599,10 +632,16 @@ static int qti_handle_system_kdf(const struct hwkm_cmd *cmd_in,
serialize_kdf_bsve(&bsve, &cmd_in->kdf.bsve, cmd_in->kdf.mks);
WRITE_TO_KDF_PACKET(cmd_ptr, &bsve, MAX_BSVE_LENGTH);
} else {
// Skip the remaining 3 bytes of the current word
cmd_ptr += 3 * (sizeof(u8));
// Skip 4 bytes to align to start of context.
cmd_ptr += 4 * (sizeof(u8));
}
/*
* Reorder context to reverse context bytes at the 8 byte
* boundary. This is because crypto lib reads at this
* boundary when populating the AD.
*/
reorder_ctx((u8 *) cmd_in->kdf.ctx, cmd_in->kdf.sz);
WRITE_TO_KDF_PACKET(cmd_ptr, cmd_in->kdf.ctx, cmd_in->kdf.sz);
status = qti_hwkm_run_transaction(ICEMEM_SLAVE, cmd,
@ -724,7 +763,7 @@ static int qti_handle_keyslot_rdwr(const struct hwkm_cmd *cmd_in,
cmd_in->rdwr.sz);
// Need to reverse the key because the HW expects it in reverse
// byte order
reverse_key((u8 *) (cmd + COMMAND_KEY_VALUE_IDX),
reverse_bytes((u8 *) (cmd + COMMAND_KEY_VALUE_IDX),
HWKM_MAX_KEY_SIZE);
}
@ -750,7 +789,8 @@ static int qti_handle_keyslot_rdwr(const struct hwkm_cmd *cmd_in,
rsp + RESPONSE_KEY_VALUE_IDX, RESPONSE_KEY_LENGTH);
// Need to reverse the key because the HW returns it in
// reverse byte order
reverse_key(rsp_in->rdwr.key, HWKM_MAX_KEY_SIZE);
reverse_bytes(rsp_in->rdwr.key, HWKM_MAX_KEY_SIZE);
rsp_in->rdwr.sz = RESPONSE_KEY_LENGTH;
deserialize_policy(&rsp_in->rdwr.policy, &policy);
}