1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2 /*
3  * Shared descriptors for ahash algorithms
4  *
5  * Copyright 2017-2019 NXP
6  */
7 
8 #include "compat.h"
9 #include "desc_constr.h"
10 #include "caamhash_desc.h"
11 
12 /**
13  * cnstr_shdsc_ahash - ahash shared descriptor
14  * @desc: pointer to buffer used for descriptor construction
15  * @adata: pointer to authentication transform definitions.
16  *         A split key is required for SEC Era < 6; the size of the split key
17  *         is specified in this case.
18  *         Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1, SHA224,
19  *         SHA256, SHA384, SHA512}.
20  * @state: algorithm state OP_ALG_AS_{INIT, FINALIZE, INITFINALIZE, UPDATE}
21  * @digestsize: algorithm's digest size
22  * @ctx_len: size of Context Register
23  * @import_ctx: true if previous Context Register needs to be restored
24  *              must be true for ahash update and final
25  *              must be false for for ahash first and digest
26  * @era: SEC Era
27  */
28 void cnstr_shdsc_ahash(u32 * const desc, struct alginfo *adata, u32 state,
29 		       int digestsize, int ctx_len, bool import_ctx, int era)
30 {
31 	u32 op = adata->algtype;
32 
33 	init_sh_desc(desc, HDR_SHARE_SERIAL);
34 
35 	/* Append key if it has been set; ahash update excluded */
36 	if (state != OP_ALG_AS_UPDATE && adata->keylen) {
37 		u32 *skip_key_load;
38 
39 		/* Skip key loading if already shared */
40 		skip_key_load = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
41 					    JUMP_COND_SHRD);
42 
43 		if (era < 6)
44 			append_key_as_imm(desc, adata->key_virt,
45 					  adata->keylen_pad,
46 					  adata->keylen, CLASS_2 |
47 					  KEY_DEST_MDHA_SPLIT | KEY_ENC);
48 		else
49 			append_proto_dkp(desc, adata);
50 
51 		set_jump_tgt_here(desc, skip_key_load);
52 
53 		op |= OP_ALG_AAI_HMAC_PRECOMP;
54 	}
55 
56 	/* If needed, import context from software */
57 	if (import_ctx)
58 		append_seq_load(desc, ctx_len, LDST_CLASS_2_CCB |
59 				LDST_SRCDST_BYTE_CONTEXT);
60 
61 	/* Class 2 operation */
62 	append_operation(desc, op | state | OP_ALG_ENCRYPT);
63 
64 	/*
65 	 * Load from buf and/or src and write to req->result or state->context
66 	 * Calculate remaining bytes to read
67 	 */
68 	append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
69 	/* Read remaining bytes */
70 	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_LAST2 |
71 			     FIFOLD_TYPE_MSG | KEY_VLF);
72 	/* Store class2 context bytes */
73 	append_seq_store(desc, digestsize, LDST_CLASS_2_CCB |
74 			 LDST_SRCDST_BYTE_CONTEXT);
75 }
76 EXPORT_SYMBOL(cnstr_shdsc_ahash);
77 
78 /**
79  * cnstr_shdsc_sk_hash - shared descriptor for symmetric key cipher-based
80  *                       hash algorithms
81  * @desc: pointer to buffer used for descriptor construction
82  * @adata: pointer to authentication transform definitions.
83  * @state: algorithm state OP_ALG_AS_{INIT, FINALIZE, INITFINALIZE, UPDATE}
84  * @digestsize: algorithm's digest size
85  * @ctx_len: size of Context Register
86  * @key_dma: I/O Virtual Address of the key
87  */
88 void cnstr_shdsc_sk_hash(u32 * const desc, struct alginfo *adata, u32 state,
89 			 int digestsize, int ctx_len, dma_addr_t key_dma)
90 {
91 	u32 *skip_key_load;
92 
93 	init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
94 
95 	/* Skip loading of key, context if already shared */
96 	skip_key_load = append_jump(desc, JUMP_TEST_ALL | JUMP_COND_SHRD);
97 
98 	if (state == OP_ALG_AS_INIT || state == OP_ALG_AS_INITFINAL) {
99 		append_key_as_imm(desc, adata->key_virt, adata->keylen,
100 				  adata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
101 	} else { /* UPDATE, FINALIZE */
102 		if (is_xcbc_aes(adata->algtype))
103 			/* Load K1 */
104 			append_key(desc, adata->key_dma, adata->keylen,
105 				   CLASS_1 | KEY_DEST_CLASS_REG | KEY_ENC);
106 		else /* CMAC */
107 			append_key_as_imm(desc, adata->key_virt, adata->keylen,
108 					  adata->keylen, CLASS_1 |
109 					  KEY_DEST_CLASS_REG);
110 		/* Restore context */
111 		append_seq_load(desc, ctx_len, LDST_CLASS_1_CCB |
112 				LDST_SRCDST_BYTE_CONTEXT);
113 	}
114 
115 	set_jump_tgt_here(desc, skip_key_load);
116 
117 	/* Class 1 operation */
118 	append_operation(desc, adata->algtype | state | OP_ALG_ENCRYPT);
119 
120 	/*
121 	 * Load from buf and/or src and write to req->result or state->context
122 	 * Calculate remaining bytes to read
123 	 */
124 	append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
125 
126 	/* Read remaining bytes */
127 	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_LAST1 |
128 			     FIFOLD_TYPE_MSG | FIFOLDST_VLF);
129 
130 	/*
131 	 * Save context:
132 	 * - xcbc: partial hash, keys K2 and K3
133 	 * - cmac: partial hash, constant L = E(K,0)
134 	 */
135 	append_seq_store(desc, digestsize, LDST_CLASS_1_CCB |
136 			 LDST_SRCDST_BYTE_CONTEXT);
137 	if (is_xcbc_aes(adata->algtype) && state == OP_ALG_AS_INIT)
138 		/* Save K1 */
139 		append_fifo_store(desc, key_dma, adata->keylen,
140 				  LDST_CLASS_1_CCB | FIFOST_TYPE_KEY_KEK);
141 }
142 EXPORT_SYMBOL(cnstr_shdsc_sk_hash);
143 
144 MODULE_LICENSE("Dual BSD/GPL");
145 MODULE_DESCRIPTION("FSL CAAM ahash descriptors support");
146 MODULE_AUTHOR("NXP Semiconductors");
147