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 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 if ((rta_sec_era <= RTA_SEC_ERA_5) && 58 ((flags & VLF) || (flags & AIDF))) { 59 pr_err("SEQKEY: Flag(s) not supported by SEC Era %d\n", 60 USER_SEC_ERA(rta_sec_era)); 61 goto err; 62 } 63 } else { 64 if ((flags & AIDF) || (flags & VLF)) { 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 if ((flags & SGF) && (flags & IMMED)) { 71 pr_err("KEY: Invalid flag. SEC PC: %d; Instr: %d\n", 72 program->current_pc, 73 program->current_instruction); 74 goto err; 75 } 76 } 77 78 if ((encrypt_flags & PTS) && 79 ((encrypt_flags & ENC) || (encrypt_flags & NWB) || 80 (key_dst == PKE))) { 81 pr_err("KEY: Invalid flag / destination. SEC PC: %d; Instr: %d\n", 82 program->current_pc, program->current_instruction); 83 goto err; 84 } 85 86 if (key_dst == AFHA_SBOX) { 87 if (rta_sec_era == RTA_SEC_ERA_7) { 88 pr_err("KEY: AFHA S-box not supported by SEC Era %d\n", 89 USER_SEC_ERA(rta_sec_era)); 90 goto err; 91 } 92 93 if (flags & IMMED) { 94 pr_err("KEY: Invalid flag. SEC PC: %d; Instr: %d\n", 95 program->current_pc, 96 program->current_instruction); 97 goto err; 98 } 99 100 /* 101 * Sbox data loaded into the ARC-4 processor must be exactly 102 * 258 bytes long, or else a data sequence error is generated. 103 */ 104 if (length != 258) { 105 pr_err("KEY: Invalid length. SEC PC: %d; Instr: %d\n", 106 program->current_pc, 107 program->current_instruction); 108 goto err; 109 } 110 } 111 112 /* write key destination and class fields */ 113 switch (key_dst) { 114 case (KEY1): 115 opcode |= KEY_DEST_CLASS1; 116 break; 117 case (KEY2): 118 opcode |= KEY_DEST_CLASS2; 119 break; 120 case (PKE): 121 opcode |= KEY_DEST_CLASS1 | KEY_DEST_PKHA_E; 122 break; 123 case (AFHA_SBOX): 124 opcode |= KEY_DEST_CLASS1 | KEY_DEST_AFHA_SBOX; 125 break; 126 case (MDHA_SPLIT_KEY): 127 opcode |= KEY_DEST_CLASS2 | KEY_DEST_MDHA_SPLIT; 128 break; 129 default: 130 pr_err("KEY: Invalid destination. SEC PC: %d; Instr: %d\n", 131 program->current_pc, program->current_instruction); 132 goto err; 133 } 134 135 /* write key length */ 136 length &= KEY_LENGTH_MASK; 137 opcode |= length; 138 139 /* write key command specific flags */ 140 if (encrypt_flags & ENC) { 141 /* Encrypted (black) keys must be padded to 8 bytes (CCM) or 142 * 16 bytes (ECB) depending on EKT bit. AES-CCM encrypted keys 143 * (EKT = 1) have 6-byte nonce and 6-byte MAC after padding. 144 */ 145 opcode |= KEY_ENC; 146 if (encrypt_flags & EKT) { 147 opcode |= KEY_EKT; 148 length = ALIGN(length, 8); 149 length += 12; 150 } else { 151 length = ALIGN(length, 16); 152 } 153 if (encrypt_flags & TK) 154 opcode |= KEY_TK; 155 } 156 if (encrypt_flags & NWB) 157 opcode |= KEY_NWB; 158 if (encrypt_flags & PTS) 159 opcode |= KEY_PTS; 160 161 /* write general command flags */ 162 if (!is_seq_cmd) { 163 if (flags & IMMED) 164 opcode |= KEY_IMM; 165 if (flags & SGF) 166 opcode |= KEY_SGF; 167 } else { 168 if (flags & AIDF) 169 opcode |= KEY_AIDF; 170 if (flags & VLF) 171 opcode |= KEY_VLF; 172 } 173 174 __rta_out32(program, opcode); 175 program->current_instruction++; 176 177 if (flags & IMMED) 178 __rta_inline_data(program, src, flags & __COPY_MASK, length); 179 else 180 __rta_out64(program, program->ps, src); 181 182 return (int)start_pc; 183 184 err: 185 program->first_error_pc = start_pc; 186 program->current_instruction++; 187 return -EINVAL; 188 } 189 190 #endif /* __RTA_KEY_CMD_H__ */ 191