New upstream version 17.08
[deb_dpdk.git] / drivers / crypto / dpaa2_sec / hw / rta / key_cmd.h
1 /*-
2  * This file is provided under a dual BSD/GPLv2 license. When using or
3  * redistributing this file, you may do so under either license.
4  *
5  *   BSD LICENSE
6  *
7  * Copyright 2008-2016 Freescale Semiconductor Inc.
8  * Copyright 2016 NXP.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  * * Neither the name of the above-listed copyright holders nor the
18  * names of any contributors may be used to endorse or promote products
19  * derived from this software without specific prior written permission.
20  *
21  *   GPL LICENSE SUMMARY
22  *
23  * ALTERNATIVELY, this software may be distributed under the terms of the
24  * GNU General Public License ("GPL") as published by the Free Software
25  * Foundation, either version 2 of that License or (at your option) any
26  * later version.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
32  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  */
40
41 #ifndef __RTA_KEY_CMD_H__
42 #define __RTA_KEY_CMD_H__
43
44 extern enum rta_sec_era rta_sec_era;
45
46 /* Allowed encryption flags for each SEC Era */
47 static const uint32_t key_enc_flags[] = {
48         ENC,
49         ENC | NWB | EKT | TK,
50         ENC | NWB | EKT | TK,
51         ENC | NWB | EKT | TK,
52         ENC | NWB | EKT | TK,
53         ENC | NWB | EKT | TK,
54         ENC | NWB | EKT | TK | PTS,
55         ENC | NWB | EKT | TK | PTS
56 };
57
58 static inline int
59 rta_key(struct program *program, uint32_t key_dst,
60         uint32_t encrypt_flags, uint64_t src, uint32_t length,
61         uint32_t flags)
62 {
63         uint32_t opcode = 0;
64         bool is_seq_cmd = false;
65         unsigned int start_pc = program->current_pc;
66
67         if (encrypt_flags & ~key_enc_flags[rta_sec_era]) {
68                 pr_err("KEY: Flag(s) not supported by SEC Era %d\n",
69                        USER_SEC_ERA(rta_sec_era));
70                 goto err;
71         }
72
73         /* write cmd type */
74         if (flags & SEQ) {
75                 opcode = CMD_SEQ_KEY;
76                 is_seq_cmd = true;
77         } else {
78                 opcode = CMD_KEY;
79         }
80
81         /* check parameters */
82         if (is_seq_cmd) {
83                 if ((flags & IMMED) || (flags & SGF)) {
84                         pr_err("SEQKEY: Invalid flag. SEC PC: %d; Instr: %d\n",
85                                program->current_pc,
86                                program->current_instruction);
87                         goto err;
88                 }
89                 if ((rta_sec_era <= RTA_SEC_ERA_5) &&
90                     ((flags & VLF) || (flags & AIDF))) {
91                         pr_err("SEQKEY: Flag(s) not supported by SEC Era %d\n",
92                                USER_SEC_ERA(rta_sec_era));
93                         goto err;
94                 }
95         } else {
96                 if ((flags & AIDF) || (flags & VLF)) {
97                         pr_err("KEY: Invalid flag. SEC PC: %d; Instr: %d\n",
98                                program->current_pc,
99                                program->current_instruction);
100                         goto err;
101                 }
102                 if ((flags & SGF) && (flags & IMMED)) {
103                         pr_err("KEY: Invalid flag. SEC PC: %d; Instr: %d\n",
104                                program->current_pc,
105                                program->current_instruction);
106                         goto err;
107                 }
108         }
109
110         if ((encrypt_flags & PTS) &&
111             ((encrypt_flags & ENC) || (encrypt_flags & NWB) ||
112              (key_dst == PKE))) {
113                 pr_err("KEY: Invalid flag / destination. SEC PC: %d; Instr: %d\n",
114                        program->current_pc, program->current_instruction);
115                 goto err;
116         }
117
118         if (key_dst == AFHA_SBOX) {
119                 if (rta_sec_era == RTA_SEC_ERA_7) {
120                         pr_err("KEY: AFHA S-box not supported by SEC Era %d\n",
121                                USER_SEC_ERA(rta_sec_era));
122                         goto err;
123                 }
124
125                 if (flags & IMMED) {
126                         pr_err("KEY: Invalid flag. SEC PC: %d; Instr: %d\n",
127                                program->current_pc,
128                                program->current_instruction);
129                         goto err;
130                 }
131
132                 /*
133                  * Sbox data loaded into the ARC-4 processor must be exactly
134                  * 258 bytes long, or else a data sequence error is generated.
135                  */
136                 if (length != 258) {
137                         pr_err("KEY: Invalid length. SEC PC: %d; Instr: %d\n",
138                                program->current_pc,
139                                program->current_instruction);
140                         goto err;
141                 }
142         }
143
144         /* write key destination and class fields */
145         switch (key_dst) {
146         case (KEY1):
147                 opcode |= KEY_DEST_CLASS1;
148                 break;
149         case (KEY2):
150                 opcode |= KEY_DEST_CLASS2;
151                 break;
152         case (PKE):
153                 opcode |= KEY_DEST_CLASS1 | KEY_DEST_PKHA_E;
154                 break;
155         case (AFHA_SBOX):
156                 opcode |= KEY_DEST_CLASS1 | KEY_DEST_AFHA_SBOX;
157                 break;
158         case (MDHA_SPLIT_KEY):
159                 opcode |= KEY_DEST_CLASS2 | KEY_DEST_MDHA_SPLIT;
160                 break;
161         default:
162                 pr_err("KEY: Invalid destination. SEC PC: %d; Instr: %d\n",
163                        program->current_pc, program->current_instruction);
164                 goto err;
165         }
166
167         /* write key length */
168         length &= KEY_LENGTH_MASK;
169         opcode |= length;
170
171         /* write key command specific flags */
172         if (encrypt_flags & ENC) {
173                 /* Encrypted (black) keys must be padded to 8 bytes (CCM) or
174                  * 16 bytes (ECB) depending on EKT bit. AES-CCM encrypted keys
175                  * (EKT = 1) have 6-byte nonce and 6-byte MAC after padding.
176                  */
177                 opcode |= KEY_ENC;
178                 if (encrypt_flags & EKT) {
179                         opcode |= KEY_EKT;
180                         length = ALIGN(length, 8);
181                         length += 12;
182                 } else {
183                         length = ALIGN(length, 16);
184                 }
185                 if (encrypt_flags & TK)
186                         opcode |= KEY_TK;
187         }
188         if (encrypt_flags & NWB)
189                 opcode |= KEY_NWB;
190         if (encrypt_flags & PTS)
191                 opcode |= KEY_PTS;
192
193         /* write general command flags */
194         if (!is_seq_cmd) {
195                 if (flags & IMMED)
196                         opcode |= KEY_IMM;
197                 if (flags & SGF)
198                         opcode |= KEY_SGF;
199         } else {
200                 if (flags & AIDF)
201                         opcode |= KEY_AIDF;
202                 if (flags & VLF)
203                         opcode |= KEY_VLF;
204         }
205
206         __rta_out32(program, opcode);
207         program->current_instruction++;
208
209         if (flags & IMMED)
210                 __rta_inline_data(program, src, flags & __COPY_MASK, length);
211         else
212                 __rta_out64(program, program->ps, src);
213
214         return (int)start_pc;
215
216  err:
217         program->first_error_pc = start_pc;
218         program->current_instruction++;
219         return -EINVAL;
220 }
221
222 #endif /* __RTA_KEY_CMD_H__ */