d6da3ff455760986e552f35bc1b21008843554cf
[dpdk.git] / drivers / crypto / dpaa2_sec / hw / rta / key_cmd.h
1 /*
2  * Copyright 2008-2016 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+
5  */
6
7 #ifndef __RTA_KEY_CMD_H__
8 #define __RTA_KEY_CMD_H__
9
10 extern enum rta_sec_era rta_sec_era;
11
12 /* Allowed encryption flags for each SEC Era */
13 static const uint32_t key_enc_flags[] = {
14         ENC,
15         ENC | NWB | EKT | TK,
16         ENC | NWB | EKT | TK,
17         ENC | NWB | EKT | TK,
18         ENC | NWB | EKT | TK,
19         ENC | NWB | EKT | TK,
20         ENC | NWB | EKT | TK | PTS,
21         ENC | NWB | EKT | TK | PTS
22 };
23
24 static inline int
25 rta_key(struct program *program, uint32_t key_dst,
26         uint32_t encrypt_flags, uint64_t src, uint32_t length,
27         uint32_t flags)
28 {
29         uint32_t opcode = 0;
30         bool is_seq_cmd = false;
31         unsigned int start_pc = program->current_pc;
32
33         if (encrypt_flags & ~key_enc_flags[rta_sec_era]) {
34                 pr_err("KEY: Flag(s) not supported by SEC Era %d\n",
35                        USER_SEC_ERA(rta_sec_era));
36                 goto err;
37         }
38
39         /* write cmd type */
40         if (flags & SEQ) {
41                 opcode = CMD_SEQ_KEY;
42                 is_seq_cmd = true;
43         } else {
44                 opcode = CMD_KEY;
45         }
46
47         /* check parameters */
48         if (is_seq_cmd) {
49                 if ((flags & IMMED) || (flags & SGF)) {
50                         pr_err("SEQKEY: Invalid flag. SEC PC: %d; Instr: %d\n",
51                                program->current_pc,
52                                program->current_instruction);
53                         goto err;
54                 }
55                 if ((rta_sec_era <= RTA_SEC_ERA_5) &&
56                     ((flags & VLF) || (flags & AIDF))) {
57                         pr_err("SEQKEY: Flag(s) not supported by SEC Era %d\n",
58                                USER_SEC_ERA(rta_sec_era));
59                         goto err;
60                 }
61         } else {
62                 if ((flags & AIDF) || (flags & VLF)) {
63                         pr_err("KEY: Invalid flag. SEC PC: %d; Instr: %d\n",
64                                program->current_pc,
65                                program->current_instruction);
66                         goto err;
67                 }
68                 if ((flags & SGF) && (flags & IMMED)) {
69                         pr_err("KEY: Invalid flag. SEC PC: %d; Instr: %d\n",
70                                program->current_pc,
71                                program->current_instruction);
72                         goto err;
73                 }
74         }
75
76         if ((encrypt_flags & PTS) &&
77             ((encrypt_flags & ENC) || (encrypt_flags & NWB) ||
78              (key_dst == PKE))) {
79                 pr_err("KEY: Invalid flag / destination. SEC PC: %d; Instr: %d\n",
80                        program->current_pc, program->current_instruction);
81                 goto err;
82         }
83
84         if (key_dst == AFHA_SBOX) {
85                 if (rta_sec_era == RTA_SEC_ERA_7) {
86                         pr_err("KEY: AFHA S-box not supported by SEC Era %d\n",
87                                USER_SEC_ERA(rta_sec_era));
88                         goto err;
89                 }
90
91                 if (flags & IMMED) {
92                         pr_err("KEY: Invalid flag. SEC PC: %d; Instr: %d\n",
93                                program->current_pc,
94                                program->current_instruction);
95                         goto err;
96                 }
97
98                 /*
99                  * Sbox data loaded into the ARC-4 processor must be exactly
100                  * 258 bytes long, or else a data sequence error is generated.
101                  */
102                 if (length != 258) {
103                         pr_err("KEY: Invalid length. SEC PC: %d; Instr: %d\n",
104                                program->current_pc,
105                                program->current_instruction);
106                         goto err;
107                 }
108         }
109
110         /* write key destination and class fields */
111         switch (key_dst) {
112         case (KEY1):
113                 opcode |= KEY_DEST_CLASS1;
114                 break;
115         case (KEY2):
116                 opcode |= KEY_DEST_CLASS2;
117                 break;
118         case (PKE):
119                 opcode |= KEY_DEST_CLASS1 | KEY_DEST_PKHA_E;
120                 break;
121         case (AFHA_SBOX):
122                 opcode |= KEY_DEST_CLASS1 | KEY_DEST_AFHA_SBOX;
123                 break;
124         case (MDHA_SPLIT_KEY):
125                 opcode |= KEY_DEST_CLASS2 | KEY_DEST_MDHA_SPLIT;
126                 break;
127         default:
128                 pr_err("KEY: Invalid destination. SEC PC: %d; Instr: %d\n",
129                        program->current_pc, program->current_instruction);
130                 goto err;
131         }
132
133         /* write key length */
134         length &= KEY_LENGTH_MASK;
135         opcode |= length;
136
137         /* write key command specific flags */
138         if (encrypt_flags & ENC) {
139                 /* Encrypted (black) keys must be padded to 8 bytes (CCM) or
140                  * 16 bytes (ECB) depending on EKT bit. AES-CCM encrypted keys
141                  * (EKT = 1) have 6-byte nonce and 6-byte MAC after padding.
142                  */
143                 opcode |= KEY_ENC;
144                 if (encrypt_flags & EKT) {
145                         opcode |= KEY_EKT;
146                         length = ALIGN(length, 8);
147                         length += 12;
148                 } else {
149                         length = ALIGN(length, 16);
150                 }
151                 if (encrypt_flags & TK)
152                         opcode |= KEY_TK;
153         }
154         if (encrypt_flags & NWB)
155                 opcode |= KEY_NWB;
156         if (encrypt_flags & PTS)
157                 opcode |= KEY_PTS;
158
159         /* write general command flags */
160         if (!is_seq_cmd) {
161                 if (flags & IMMED)
162                         opcode |= KEY_IMM;
163                 if (flags & SGF)
164                         opcode |= KEY_SGF;
165         } else {
166                 if (flags & AIDF)
167                         opcode |= KEY_AIDF;
168                 if (flags & VLF)
169                         opcode |= KEY_VLF;
170         }
171
172         __rta_out32(program, opcode);
173         program->current_instruction++;
174
175         if (flags & IMMED)
176                 __rta_inline_data(program, src, flags & __COPY_MASK, length);
177         else
178                 __rta_out64(program, program->ps, src);
179
180         return (int)start_pc;
181
182  err:
183         program->first_error_pc = start_pc;
184         program->current_instruction++;
185         return -EINVAL;
186 }
187
188 #endif /* __RTA_KEY_CMD_H__ */