Commit 57660b11 authored by Antoine Tenart's avatar Antoine Tenart Committed by Herbert Xu

crypto: inside-secure - implement IV retrieval

This patch adds support for retrieving intermediate IV from the crypto
engine when using the CBC block mode with AES and (3)DES. The retrieved
IV is copied to the request IV buffer, as requested by the kernel crypto
API.

This fix boot tests added by
commit 8efd972e ("crypto: testmgr - support checking skcipher output IV").
Signed-off-by: default avatarAntoine Tenart <antoine.tenart@bootlin.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent ccd65a20
...@@ -339,6 +339,7 @@ struct safexcel_context_record { ...@@ -339,6 +339,7 @@ struct safexcel_context_record {
#define CONTEXT_CONTROL_IV3 BIT(8) #define CONTEXT_CONTROL_IV3 BIT(8)
#define CONTEXT_CONTROL_DIGEST_CNT BIT(9) #define CONTEXT_CONTROL_DIGEST_CNT BIT(9)
#define CONTEXT_CONTROL_COUNTER_MODE BIT(10) #define CONTEXT_CONTROL_COUNTER_MODE BIT(10)
#define CONTEXT_CONTROL_CRYPTO_STORE BIT(12)
#define CONTEXT_CONTROL_HASH_STORE BIT(19) #define CONTEXT_CONTROL_HASH_STORE BIT(19)
/* The hash counter given to the engine in the context has a granularity of /* The hash counter given to the engine in the context has a granularity of
...@@ -431,6 +432,10 @@ struct safexcel_token { ...@@ -431,6 +432,10 @@ struct safexcel_token {
#define EIP197_TOKEN_HASH_RESULT_VERIFY BIT(16) #define EIP197_TOKEN_HASH_RESULT_VERIFY BIT(16)
#define EIP197_TOKEN_CTX_OFFSET(x) (x)
#define EIP197_TOKEN_DIRECTION_EXTERNAL BIT(11)
#define EIP197_TOKEN_EXEC_IF_SUCCESSFUL (0x1 << 12)
#define EIP197_TOKEN_STAT_LAST_HASH BIT(0) #define EIP197_TOKEN_STAT_LAST_HASH BIT(0)
#define EIP197_TOKEN_STAT_LAST_PACKET BIT(1) #define EIP197_TOKEN_STAT_LAST_PACKET BIT(1)
#define EIP197_TOKEN_OPCODE_DIRECTION 0x0 #define EIP197_TOKEN_OPCODE_DIRECTION 0x0
...@@ -438,6 +443,7 @@ struct safexcel_token { ...@@ -438,6 +443,7 @@ struct safexcel_token {
#define EIP197_TOKEN_OPCODE_NOOP EIP197_TOKEN_OPCODE_INSERT #define EIP197_TOKEN_OPCODE_NOOP EIP197_TOKEN_OPCODE_INSERT
#define EIP197_TOKEN_OPCODE_RETRIEVE 0x4 #define EIP197_TOKEN_OPCODE_RETRIEVE 0x4
#define EIP197_TOKEN_OPCODE_VERIFY 0xd #define EIP197_TOKEN_OPCODE_VERIFY 0xd
#define EIP197_TOKEN_OPCODE_CTX_ACCESS 0xe
#define EIP197_TOKEN_OPCODE_BYPASS GENMASK(3, 0) #define EIP197_TOKEN_OPCODE_BYPASS GENMASK(3, 0)
static inline void eip197_noop_token(struct safexcel_token *token) static inline void eip197_noop_token(struct safexcel_token *token)
...@@ -448,6 +454,8 @@ static inline void eip197_noop_token(struct safexcel_token *token) ...@@ -448,6 +454,8 @@ static inline void eip197_noop_token(struct safexcel_token *token)
/* Instructions */ /* Instructions */
#define EIP197_TOKEN_INS_INSERT_HASH_DIGEST 0x1c #define EIP197_TOKEN_INS_INSERT_HASH_DIGEST 0x1c
#define EIP197_TOKEN_INS_ORIGIN_IV0 0x14
#define EIP197_TOKEN_INS_ORIGIN_LEN(x) ((x) << 5)
#define EIP197_TOKEN_INS_TYPE_OUTPUT BIT(5) #define EIP197_TOKEN_INS_TYPE_OUTPUT BIT(5)
#define EIP197_TOKEN_INS_TYPE_HASH BIT(6) #define EIP197_TOKEN_INS_TYPE_HASH BIT(6)
#define EIP197_TOKEN_INS_TYPE_CRYTO BIT(7) #define EIP197_TOKEN_INS_TYPE_CRYTO BIT(7)
......
...@@ -59,26 +59,26 @@ static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv, ...@@ -59,26 +59,26 @@ static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv,
u32 length) u32 length)
{ {
struct safexcel_token *token; struct safexcel_token *token;
unsigned offset = 0; u32 offset = 0, block_sz = 0;
if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) { if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) {
switch (ctx->alg) { switch (ctx->alg) {
case SAFEXCEL_DES: case SAFEXCEL_DES:
offset = DES_BLOCK_SIZE / sizeof(u32); block_sz = DES_BLOCK_SIZE;
memcpy(cdesc->control_data.token, iv, DES_BLOCK_SIZE);
cdesc->control_data.options |= EIP197_OPTION_2_TOKEN_IV_CMD; cdesc->control_data.options |= EIP197_OPTION_2_TOKEN_IV_CMD;
break; break;
case SAFEXCEL_3DES: case SAFEXCEL_3DES:
offset = DES3_EDE_BLOCK_SIZE / sizeof(u32); block_sz = DES3_EDE_BLOCK_SIZE;
memcpy(cdesc->control_data.token, iv, DES3_EDE_BLOCK_SIZE);
cdesc->control_data.options |= EIP197_OPTION_2_TOKEN_IV_CMD; cdesc->control_data.options |= EIP197_OPTION_2_TOKEN_IV_CMD;
break; break;
case SAFEXCEL_AES: case SAFEXCEL_AES:
offset = AES_BLOCK_SIZE / sizeof(u32); block_sz = AES_BLOCK_SIZE;
memcpy(cdesc->control_data.token, iv, AES_BLOCK_SIZE);
cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD; cdesc->control_data.options |= EIP197_OPTION_4_TOKEN_IV_CMD;
break; break;
} }
offset = block_sz / sizeof(u32);
memcpy(cdesc->control_data.token, iv, block_sz);
} }
token = (struct safexcel_token *)(cdesc->control_data.token + offset); token = (struct safexcel_token *)(cdesc->control_data.token + offset);
...@@ -90,6 +90,25 @@ static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv, ...@@ -90,6 +90,25 @@ static void safexcel_skcipher_token(struct safexcel_cipher_ctx *ctx, u8 *iv,
token[0].instructions = EIP197_TOKEN_INS_LAST | token[0].instructions = EIP197_TOKEN_INS_LAST |
EIP197_TOKEN_INS_TYPE_CRYTO | EIP197_TOKEN_INS_TYPE_CRYTO |
EIP197_TOKEN_INS_TYPE_OUTPUT; EIP197_TOKEN_INS_TYPE_OUTPUT;
if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) {
u32 last = (EIP197_MAX_TOKENS - 1) - offset;
token[last].opcode = EIP197_TOKEN_OPCODE_CTX_ACCESS;
token[last].packet_length = EIP197_TOKEN_DIRECTION_EXTERNAL |
EIP197_TOKEN_EXEC_IF_SUCCESSFUL|
EIP197_TOKEN_CTX_OFFSET(0x2);
token[last].stat = EIP197_TOKEN_STAT_LAST_HASH |
EIP197_TOKEN_STAT_LAST_PACKET;
token[last].instructions =
EIP197_TOKEN_INS_ORIGIN_LEN(block_sz / sizeof(u32)) |
EIP197_TOKEN_INS_ORIGIN_IV0;
/* Store the updated IV values back in the internal context
* registers.
*/
cdesc->control_data.control1 |= CONTEXT_CONTROL_CRYPTO_STORE;
}
} }
static void safexcel_aead_token(struct safexcel_cipher_ctx *ctx, u8 *iv, static void safexcel_aead_token(struct safexcel_cipher_ctx *ctx, u8 *iv,
...@@ -559,6 +578,7 @@ static int safexcel_skcipher_handle_result(struct safexcel_crypto_priv *priv, ...@@ -559,6 +578,7 @@ static int safexcel_skcipher_handle_result(struct safexcel_crypto_priv *priv,
{ {
struct skcipher_request *req = skcipher_request_cast(async); struct skcipher_request *req = skcipher_request_cast(async);
struct safexcel_cipher_req *sreq = skcipher_request_ctx(req); struct safexcel_cipher_req *sreq = skcipher_request_ctx(req);
struct safexcel_cipher_ctx *ctx = crypto_tfm_ctx(async->tfm);
int err; int err;
if (sreq->needs_inv) { if (sreq->needs_inv) {
...@@ -569,6 +589,24 @@ static int safexcel_skcipher_handle_result(struct safexcel_crypto_priv *priv, ...@@ -569,6 +589,24 @@ static int safexcel_skcipher_handle_result(struct safexcel_crypto_priv *priv,
err = safexcel_handle_req_result(priv, ring, async, req->src, err = safexcel_handle_req_result(priv, ring, async, req->src,
req->dst, req->cryptlen, sreq, req->dst, req->cryptlen, sreq,
should_complete, ret); should_complete, ret);
if (ctx->mode == CONTEXT_CONTROL_CRYPTO_MODE_CBC) {
u32 block_sz = 0;
switch (ctx->alg) {
case SAFEXCEL_DES:
block_sz = DES_BLOCK_SIZE;
break;
case SAFEXCEL_3DES:
block_sz = DES3_EDE_BLOCK_SIZE;
break;
case SAFEXCEL_AES:
block_sz = AES_BLOCK_SIZE;
break;
}
memcpy(req->iv, ctx->base.ctxr->data, block_sz);
}
} }
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment