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