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