diff --git a/drivers/soc/qcom/crypto-qti-hwkm.c b/drivers/soc/qcom/crypto-qti-hwkm.c index 6f42ab833686..e8fe8350adc9 100644 --- a/drivers/soc/qcom/crypto-qti-hwkm.c +++ b/drivers/soc/qcom/crypto-qti-hwkm.c @@ -9,6 +9,7 @@ #include #include #include +#include #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; diff --git a/drivers/soc/qcom/hwkm.c b/drivers/soc/qcom/hwkm.c index b0566c176550..3a2e62407100 100644 --- a/drivers/soc/qcom/hwkm.c +++ b/drivers/soc/qcom/hwkm.c @@ -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); }