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